Skip to content

Commit

Permalink
add extra-sources module
Browse files Browse the repository at this point in the history
  • Loading branch information
pedroSG94 committed Sep 14, 2024
2 parents 7a70efa + ee0ef5b commit f170b48
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 10 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ allprojects {
}
dependencies {
implementation 'com.github.pedroSG94.RootEncoder:library:2.5.0'
//Optional, allow use BitmapSource, CameraXSource and CameraUvcSource
implementation 'com.github.pedroSG94.RootEncoder:extra-sources:2.5.0'
}
```
Expand All @@ -76,6 +78,7 @@ dependencies {
## Features:

- [x] Android min API 16.
- [x] Extra video sources minAPI 21+ (BitmapSource, CameraXSource and CameraUvcSource)

### Encoder:

Expand Down Expand Up @@ -135,8 +138,6 @@ https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html

https://github.com/pedroSG94/RTSP-Server

[Support UVC camera (use rotation example and change the video source on fly using the menu):](https://github.com/pedroSG94/RootEncoder/tree/feature/usb-camera)

### 3rd party projects:

Projects related with the library developed by other users.
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ android {

dependencies {
implementation(project(":library"))
implementation(project(":extra-sources"))
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.multidex)
implementation(libs.bundles.androidx.camera)
}
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>

<!-- This is only to allow compile extra-sources modules in app with min version 16. Never do it-->
<uses-sdk tools:overrideLibrary="com.pedro.extrasources,com.serenegiant.uvccamera,androidx.core.ktx,androidx.core,androidx.annotation.experimental"/>

<application
android:name=".App"
android:requestLegacyExternalStorage="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.pedro.library.base.recording.RecordController
import com.pedro.library.generic.GenericStream
import com.pedro.encoder.input.sources.video.Camera1Source
import com.pedro.encoder.input.sources.video.Camera2Source
import com.pedro.extrasources.CameraXSource
import com.pedro.streamer.R
import com.pedro.streamer.utils.PathUtils
import com.pedro.streamer.utils.toast
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/com/pedro/streamer/rotation/RotationActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ import androidx.appcompat.app.AppCompatActivity
import com.pedro.encoder.input.sources.audio.MicrophoneSource
import com.pedro.encoder.input.sources.video.Camera1Source
import com.pedro.encoder.input.sources.video.Camera2Source
import com.pedro.encoder.input.video.CameraHelper
import com.pedro.extrasources.BitmapSource
import com.pedro.extrasources.CameraUvcSource
import com.pedro.extrasources.CameraXSource
import com.pedro.streamer.R
import com.pedro.streamer.utils.FilterMenu
import com.pedro.streamer.utils.toast
Expand Down Expand Up @@ -74,19 +78,28 @@ class RotationActivity : AppCompatActivity(), OnTouchListener {
R.id.video_source_camera1 -> {
currentVideoSource = item.updateMenuColor(this, currentVideoSource)
cameraFragment.genericStream.changeVideoSource(Camera1Source(applicationContext))
updateOrientation(false)
}
R.id.video_source_camera2 -> {
currentVideoSource = item.updateMenuColor(this, currentVideoSource)
cameraFragment.genericStream.changeVideoSource(Camera2Source(applicationContext))
updateOrientation(false)
}
R.id.video_source_camerax -> {
currentVideoSource = item.updateMenuColor(this, currentVideoSource)
cameraFragment.genericStream.changeVideoSource(CameraXSource(applicationContext))
updateOrientation(false)
}
R.id.video_source_camera_uvc -> {
currentVideoSource = item.updateMenuColor(this, currentVideoSource)
cameraFragment.genericStream.changeVideoSource(CameraUvcSource())
updateOrientation(true)
}
R.id.video_source_bitmap -> {
currentVideoSource = item.updateMenuColor(this, currentVideoSource)
val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)
cameraFragment.genericStream.changeVideoSource(BitmapSource(bitmap))
updateOrientation(false)
}
R.id.audio_source_microphone -> {
currentAudioSource = item.updateMenuColor(this, currentAudioSource)
Expand Down Expand Up @@ -121,4 +134,17 @@ class RotationActivity : AppCompatActivity(), OnTouchListener {
}
return false
}

private fun updateOrientation(isUvc: Boolean) {
//UVC cameras can't adapt orientation depend of the device orientation so we need force use always landscape orientations
if (isUvc) {
cameraFragment.genericStream.getGlInterface().autoHandleOrientation = false
cameraFragment.genericStream.getGlInterface().setCameraOrientation(0)
} else { //Reset orientation to the correct orientation depend of device orientation
cameraFragment.genericStream.getGlInterface().autoHandleOrientation = true
val orientation = CameraHelper.getCameraOrientation(this)
cameraFragment.genericStream.getGlInterface().setCameraOrientation(if (orientation == 0) 270 else orientation - 90)
cameraFragment.genericStream.getGlInterface().setIsPortrait(CameraHelper.isPortrait(this))
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/res/menu/rotation_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
android:title="@string/camerax"
android:id="@+id/video_source_camerax"
/>
<item
android:title="@string/camera_uvc"
android:id="@+id/video_source_camera_uvc"
/>
<item
android:title="@string/bitmap"
android:id="@+id/video_source_bitmap"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<string name="camera1">Camera1</string>
<string name="camera2">Camera2</string>
<string name="camerax">CameraX</string>
<string name="camera_uvc">CameraUVC</string>
<string name="bitmap">Bitmap</string>

</resources>
1 change: 1 addition & 0 deletions encoder/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ afterEvaluate {
}

dependencies {
implementation(libs.kotlinx.coroutines.android)
testImplementation(libs.junit)
api(libs.androidx.annotation)
api(project(":common"))
Expand Down
1 change: 1 addition & 0 deletions extra-sources/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
58 changes: 58 additions & 0 deletions extra-sources/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin)
id(libs.plugins.maven.publish.get().pluginId)
alias(libs.plugins.jetbrains.dokka)
}

android {
namespace = "com.pedro.extrasources"
compileSdk = 34

defaultConfig {
minSdk = 21
lint.targetSdk = 34
}
buildTypes {
release {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}

publishing {
singleVariant("release")
}
}

afterEvaluate {
publishing {
publications {
// Creates a Maven publication called "release".
create<MavenPublication>("release") {
// Applies the component for the release build variant.
from(components["release"])

// You can then customize attributes of the publication as shown below.
groupId = libs.versions.libraryGroup.get()
artifactId = "extra-sources"
version = libs.versions.versionName.get()
}
}
}
}

dependencies {
implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.appcompat)
implementation(libs.bundles.androidx.camera)
implementation(libs.uvcandroid)
testImplementation(libs.junit)
api(project(":encoder"))
}
4 changes: 4 additions & 0 deletions extra-sources/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.pedro.streamer.rotation
package com.pedro.extrasources

import android.graphics.Bitmap
import android.graphics.Paint
Expand Down
104 changes: 104 additions & 0 deletions extra-sources/src/main/java/com/pedro/extrasources/CameraUvcSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
*
* * Copyright (C) 2024 pedroSG94.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/

package com.pedro.extrasources

import android.graphics.SurfaceTexture
import android.hardware.usb.UsbDevice
import android.view.Surface
import com.herohan.uvcapp.CameraHelper
import com.herohan.uvcapp.ICameraHelper
import com.pedro.encoder.input.sources.OrientationForced
import com.pedro.encoder.input.sources.video.VideoSource
import com.pedro.encoder.input.video.Camera2ResolutionCalculator
import com.serenegiant.usb.Size
import kotlin.math.abs


/**
* Created by pedro on 10/9/24.
*/
class CameraUvcSource: VideoSource() {

private var cameraHelper: ICameraHelper? = null
private var running = false
private var surface: Surface? = null

override fun create(width: Int, height: Int, fps: Int, rotation: Int): Boolean {
return true
}

override fun start(surfaceTexture: SurfaceTexture) {
this.surfaceTexture = surfaceTexture
surface = Surface(surfaceTexture)
cameraHelper = CameraHelper()
cameraHelper?.setStateCallback(stateCallback)
running = true
}

override fun stop() {
surface?.let { cameraHelper?.removeSurface(it) }
surface?.release()
surface = null
cameraHelper?.release()
cameraHelper = null
running = false
}

override fun release() {
}

override fun isRunning(): Boolean = running

override fun getOrientationConfig(): OrientationForced = OrientationForced.LANDSCAPE

private val stateCallback: ICameraHelper.StateCallback = object : ICameraHelper.StateCallback {
override fun onAttach(device: UsbDevice) {
cameraHelper?.selectDevice(device)
}

override fun onDeviceOpen(device: UsbDevice, isFirstOpen: Boolean) {
cameraHelper?.openCamera()
}

override fun onCameraOpen(device: UsbDevice) {
cameraHelper?.startPreview()
val resolution = getOptimalResolution()
if (resolution != null) cameraHelper?.previewSize = resolution
surface?.let { cameraHelper?.addSurface(it, false) }
}

override fun onCameraClose(device: UsbDevice) {

}

override fun onDeviceClose(device: UsbDevice) {}

override fun onDetach(device: UsbDevice) {}

override fun onCancel(device: UsbDevice) {}
}

private fun getOptimalResolution(): Size? {
val supportedSizes = cameraHelper?.supportedSizeList ?: return null
val supportedResolutions = supportedSizes.map { android.util.Size(it.width, it.height) }.toTypedArray()
val resolution = Camera2ResolutionCalculator.getOptimalResolution(android.util.Size(width, height), supportedResolutions)
val validSizes = supportedSizes.filter { it.width == resolution.width && it.height == resolution.height }
return validSizes.minByOrNull { abs(fps - it.fps) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
* limitations under the License.
*/

package com.pedro.streamer.rotation
package com.pedro.extrasources

import android.content.Context
import android.graphics.SurfaceTexture
import android.os.Build
import android.util.Range
import android.util.Size
import android.view.Surface
import androidx.annotation.RequiresApi
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.Preview
Expand All @@ -40,7 +38,6 @@ import java.util.concurrent.Executors
/**
* Created by pedro on 16/2/24.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class CameraXSource(
private val context: Context,
): VideoSource(), LifecycleOwner {
Expand Down Expand Up @@ -118,5 +115,5 @@ class CameraXSource(
}
}

override fun getLifecycle(): Lifecycle = lifecycleRegistry
override val lifecycle: Lifecycle = lifecycleRegistry
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ annotation = "1.8.2"
coroutines = "1.9.0"
junit = "4.13.2"
mockito = "5.4.0"
uvcandroid = "1.0.7"

[libraries]
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
Expand All @@ -31,6 +32,7 @@ junit = { module = "junit:junit", version.ref = "junit" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockito" }
uvcandroid = { module = "com.herohan:UVCAndroid", version.ref = "uvcandroid" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ dependencyResolutionManagement {
}

rootProject.name = "RootEncoder"
include(":app", ":rtmp", ":encoder", ":rtsp", ":library", ":srt", ":udp", ":common")
include(":app", ":rtmp", ":encoder", ":rtsp", ":library", ":srt", ":udp", ":common")
include(":extra-sources")

0 comments on commit f170b48

Please sign in to comment.