Skip to content

Commit

Permalink
refactor(*): move current streamer to single
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee committed Jan 3, 2025
1 parent e89e80a commit 1bc6416
Show file tree
Hide file tree
Showing 109 changed files with 669 additions and 696 deletions.
10 changes: 5 additions & 5 deletions DEVELOPER_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ streamer.videoEncoder!!.bitrate = 2000000

## Streamers

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

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

To endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to the `Streamer`
Expand Down Expand Up @@ -160,7 +160,7 @@ They implement the `ISink` interface.
The implement the `ICoroutineStreamer` interface.

@startuml
class DefaultStreamer {
class SingleStreamer {

+ videoSource: IVideoSource
+ audioSource: IAudioSource
Expand All @@ -172,7 +172,7 @@ class DefaultStreamer {
@enduml

@startuml
rectangle DefaultCameraStreamer {
rectangle CameraSingleStreamer {
[CameraSource] as VideoSource
[MicrophoneSource] as AudioSource
[Encoder] as VideoEncoder
Expand Down
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,16 @@ There are 2 types of streamers:

```kotlin
// For coroutine based
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())
// For callback based
// val streamer = DefaultCameraCallbackStreamer(context = requireContext())
// val streamer = CameraCallbackSingleStreamer(context = requireContext())
```

4. Configures audio and video settings

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())

val audioConfig = AudioConfig(
startBitrate = 128000,
Expand All @@ -169,10 +169,10 @@ streamer.configure(audioConfig, videoConfig)

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())

/**
* If the preview is a [PreviewView]
* If the preview is a `CameraPreviewView`
*/
preview.streamer = streamer
/**
Expand All @@ -185,7 +185,7 @@ streamer.startPreview(preview)

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())


val descriptor =
Expand All @@ -203,7 +203,7 @@ streamer.startStream()

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())

streamer.stopStream()
streamer.close() // Disconnect from server or close the file
Expand Down Expand Up @@ -284,7 +284,7 @@ To set the `Streamer` orientation, you can use the `targetRotation` setter:

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())

streamer.targetRotation =
Surface.ROTATION_90 // Or Surface.ROTATION_0, Surface.ROTATION_180, Surface.ROTATION_270
Expand All @@ -303,7 +303,7 @@ extension.

```kotlin
// Already instantiated streamer
val streamer = DefaultCameraStreamer(context = requireContext())
val streamer = CameraSingleStreamer(context = requireContext())

// For callback based
val listener = object : IRotationProvider.Listener {
Expand Down Expand Up @@ -354,16 +354,16 @@ capture, encode, mux and send.They comes in multiple flavours: with different au
source . 3 types of base streamers
are available :

-`DefaultCameraStreamer`: for streaming from camera
-`DefaultScreenRecorderStreamer`: for streaming from screen
-`DefaultAudioOnlyStreamer`: for streaming audio only
-`CameraSingleStreamer`: for streaming from camera
-`ScreenRecorderSingleStreamer`: for streaming from screen
-`AudioOnlySingleStreamer`: for streaming audio only

Since 3.0.0, the endpoint of a `Streamer` is inferred from the `MediaDescriptor` object passed to
the `open` or `startStream` methods.It is possible to limit the possibility of the endpoint by
implementing your own `DynamicEndpoint.Factory` or passing a endpoint as the `Streamer` `endpoint`
parameter.To create a `Streamer` for a new source, you have to create a new `Streamer` class that
inherits
from `DefaultStreamer` .
from `SingleStreamer` .

### Get device capabilities

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.thibaultbee.streampack.core.internal.encoders

import android.media.AudioFormat
import android.media.MediaFormat
import org.junit.Assert
import org.junit.Test

class AudioCodecConfigTest {
/**
* This test required [Size] which is not available in unit test.
*/
@Test
fun equalsConfigTest() {
val audioCodecConfig = AudioCodecConfig()

Assert.assertEquals(audioCodecConfig, audioCodecConfig)
Assert.assertEquals(audioCodecConfig, AudioCodecConfig())
Assert.assertNotEquals(
audioCodecConfig,
AudioCodecConfig(mimeType = MediaFormat.MIMETYPE_AUDIO_OPUS)
)
Assert.assertNotEquals(audioCodecConfig, AudioCodecConfig(startBitrate = 1_000))
Assert.assertNotEquals(audioCodecConfig, AudioCodecConfig(sampleRate = 48000))
Assert.assertNotEquals(
audioCodecConfig,
AudioCodecConfig(channelConfig = AudioFormat.CHANNEL_IN_MONO)
)
Assert.assertNotEquals(
audioCodecConfig,
AudioCodecConfig(byteFormat = AudioFormat.ENCODING_PCM_8BIT)
)
Assert.assertNotEquals(audioCodecConfig, AudioCodecConfig(profile = 1234))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.github.thibaultbee.streampack.core.internal.encoders

import android.media.MediaFormat
import android.util.Size
import org.junit.Assert
import org.junit.Test

class VideoCodecConfigTest {
/**
* This test required [Size] which is not available in unit test.
*/
@Test
fun equalsConfigTest() {
val videoConfig = VideoCodecConfig()

Assert.assertEquals(videoConfig, videoConfig)
Assert.assertEquals(videoConfig, VideoCodecConfig())
Assert.assertNotEquals(
videoConfig,
VideoCodecConfig(mimeType = MediaFormat.MIMETYPE_VIDEO_HEVC)
)
Assert.assertNotEquals(videoConfig, VideoCodecConfig(startBitrate = 1_000))
Assert.assertNotEquals(videoConfig, VideoCodecConfig(resolution = Size(1920, 1080)))
Assert.assertNotEquals(videoConfig, VideoCodecConfig(fps = 15))
Assert.assertNotEquals(
videoConfig,
VideoCodecConfig(profile = 1234, level = videoConfig.level)
) // Level is inferred from profile
Assert.assertNotEquals(videoConfig, VideoCodecConfig(level = 1234))
Assert.assertNotEquals(videoConfig, VideoCodecConfig(gopDuration = 1234f))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.github.thibaultbee.streampack.core.internal.endpoints
import android.content.Context
import android.net.Uri
import androidx.test.platform.app.InstrumentationRegistry
import io.github.thibaultbee.streampack.core.data.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.configuration.mediadescriptor.UriMediaDescriptor
import kotlinx.coroutines.test.runTest
import org.junit.Test

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ import androidx.core.net.toUri
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.github.thibaultbee.streampack.core.data.AudioConfig
import io.github.thibaultbee.streampack.core.data.VideoConfig
import io.github.thibaultbee.streampack.core.data.mediadescriptor.MediaDescriptor
import io.github.thibaultbee.streampack.core.data.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.configuration.mediadescriptor.MediaDescriptor
import io.github.thibaultbee.streampack.core.configuration.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.internal.endpoints.IEndpointInternal
import io.github.thibaultbee.streampack.core.internal.endpoints.composites.CompositeEndpoint
import io.github.thibaultbee.streampack.core.internal.endpoints.composites.muxers.mp4.MP4Muxer
import io.github.thibaultbee.streampack.core.internal.endpoints.composites.sinks.FileSink
import io.github.thibaultbee.streampack.core.streamers.DefaultCameraStreamer
import io.github.thibaultbee.streampack.core.streamers.single.AudioConfig
import io.github.thibaultbee.streampack.core.streamers.single.CameraSingleStreamer
import io.github.thibaultbee.streampack.core.streamers.single.VideoConfig
import io.github.thibaultbee.streampack.core.streamers.single.setConfig
import io.github.thibaultbee.streampack.core.utils.FileUtils
import kotlinx.coroutines.test.runTest
import org.junit.Rule
Expand All @@ -54,9 +55,9 @@ class CameraStreamerFileTest(
) {
private val context: Context = InstrumentationRegistry.getInstrumentation().context
private val streamer = if (endpoint != null) {
DefaultCameraStreamer(context, internalEndpoint = endpoint)
CameraSingleStreamer(context, internalEndpoint = endpoint)
} else {
DefaultCameraStreamer(context)
CameraSingleStreamer(context)
}
private val info = streamer.getInfo(descriptor)

Expand Down Expand Up @@ -98,7 +99,7 @@ class CameraStreamerFileTest(
VideoConfig(mimeType = videoCodec, resolution = Size(VIDEO_WIDTH, VIDEO_HEIGHT))

// Run stream
streamer.configure(
streamer.setConfig(
audioConfig,
videoConfig
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ import androidx.core.net.toUri
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.github.thibaultbee.streampack.core.data.AudioConfig
import io.github.thibaultbee.streampack.core.data.VideoConfig
import io.github.thibaultbee.streampack.core.data.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.streamers.DefaultCameraStreamer
import io.github.thibaultbee.streampack.core.configuration.mediadescriptor.UriMediaDescriptor
import io.github.thibaultbee.streampack.core.streamers.single.AudioConfig
import io.github.thibaultbee.streampack.core.streamers.single.CameraSingleStreamer
import io.github.thibaultbee.streampack.core.streamers.single.VideoConfig
import io.github.thibaultbee.streampack.core.streamers.single.setConfig
import io.github.thibaultbee.streampack.core.utils.FileUtils
import kotlinx.coroutines.test.runTest
import org.junit.Rule
Expand All @@ -36,12 +37,12 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

/**
* Test [DefaultCameraStreamer] with multiple streams.
* Test [CameraSingleStreamer] with multiple streams.
*/
@LargeTest
class CameraStreamerMultiStreamTest {
private val context: Context = InstrumentationRegistry.getInstrumentation().context
private val streamer = DefaultCameraStreamer(context)
private val streamer = CameraSingleStreamer(context)

private val descriptors = listOf(
UriMediaDescriptor(FileUtils.createCacheFile("video.ts").toUri()),
Expand All @@ -60,7 +61,7 @@ class CameraStreamerMultiStreamTest {
val videoConfig = VideoConfig(resolution = Size(VIDEO_WIDTH, VIDEO_HEIGHT))

// Run stream
streamer.configure(
streamer.setConfig(
audioConfig,
videoConfig
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.github.thibaultbee.streampack.core.streamer.file

import io.github.thibaultbee.streampack.core.data.mediadescriptor.MediaDescriptor
import io.github.thibaultbee.streampack.core.streamers.DefaultStreamer
import io.github.thibaultbee.streampack.core.streamers.interfaces.startStream
import io.github.thibaultbee.streampack.core.configuration.mediadescriptor.MediaDescriptor
import io.github.thibaultbee.streampack.core.streamers.single.SingleStreamer
import io.github.thibaultbee.streampack.core.streamers.single.startStream
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
Expand All @@ -12,7 +12,7 @@ import kotlin.time.Duration.Companion.seconds

object StreamerUtils {
suspend fun runStream(
streamer: DefaultStreamer,
streamer: SingleStreamer,
descriptor: MediaDescriptor,
duration: Duration,
pollDuration: Duration = 1.seconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import android.media.MediaMetadataRetriever.METADATA_KEY_SAMPLERATE
import android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT
import android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH
import android.net.Uri
import io.github.thibaultbee.streampack.core.data.AudioConfig
import io.github.thibaultbee.streampack.core.data.VideoConfig
import io.github.thibaultbee.streampack.core.internal.utils.extensions.isDevicePortrait
import io.github.thibaultbee.streampack.core.streamers.single.AudioConfig
import io.github.thibaultbee.streampack.core.streamers.single.VideoConfig
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import java.io.File
Expand Down
Loading

0 comments on commit 1bc6416

Please sign in to comment.