Skip to content

Component API Reference

This document provides detailed API reference for all major components in Gazer Mobile Stream Studio.

UsbCaptureManager

Manages USB device detection, connection, and permissions.

Class Definition

class UsbCaptureManager(
    private val context: Context,
    private val usbManager: UsbManager
)

Public Interface

// Connection state observation
val connectionState: LiveData<ConnectionState>
val connectedDevice: LiveData<UsbDevice?>

// Device management
suspend fun requestPermission(device: UsbDevice): Boolean
suspend fun connectToDevice(device: UsbDevice): Result<Boolean>
fun disconnectDevice()
fun getCompatibleDevices(): List<UsbDevice>

// Device filtering
fun isCompatibleDevice(device: UsbDevice): Boolean

ConnectionState

sealed class ConnectionState {
    object Disconnected : ConnectionState()
    object Connecting : ConnectionState()
    data class Connected(val device: UsbDevice) : ConnectionState()
    data class Error(val message: String) : ConnectionState()
}

Usage Example

val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
val captureManager = UsbCaptureManager(this, usbManager)

// Observe connection state
captureManager.connectionState.observe(this) { state ->
    when (state) {
        is ConnectionState.Connected -> {
            // Device connected, start video capture
        }
        is ConnectionState.Error -> {
            // Handle connection error
        }
    }
}

// Connect to device
lifecycleScope.launch {
    val devices = captureManager.getCompatibleDevices()
    if (devices.isNotEmpty()) {
        val result = captureManager.connectToDevice(devices.first())
        // Handle connection result
    }
}

UsbVideoCapture

Captures video frames from connected USB devices.

Class Definition

class UsbVideoCapture(
    private val usbConnection: UsbDeviceConnection,
    private val usbInterface: UsbInterface
)

Public Interface

// Video capture flow
val videoFrames: Flow<VideoFrame>
val captureState: StateFlow<CaptureState>

// Capture control
suspend fun startCapture(format: VideoFormat): Result<Boolean>
suspend fun stopCapture()
fun getSupportedFormats(): List<VideoFormat>

// Frame properties
val frameWidth: Int
val frameHeight: Int
val frameRate: Float

VideoFrame

data class VideoFrame(
    val data: ByteArray,
    val format: VideoFormat,
    val width: Int,
    val height: Int,
    val timestamp: Long
)

VideoFormat

enum class VideoFormat {
    YUV420,
    NV21,
    JPEG,
    MJPEG
}

Usage Example

val videoCapture = UsbVideoCapture(connection, interface)

// Start capturing
lifecycleScope.launch {
    val result = videoCapture.startCapture(VideoFormat.YUV420)
    if (result.isSuccess) {
        // Collect video frames
        videoCapture.videoFrames.collect { frame ->
            // Process video frame
            processVideoFrame(frame)
        }
    }
}

VideoPreviewRenderer

Renders video frames to a SurfaceView for real-time preview.

Class Definition

class VideoPreviewRenderer(
    private val surfaceView: SurfaceView
) : SurfaceHolder.Callback

Public Interface

// Rendering control
suspend fun startRendering(frameFlow: Flow<VideoFrame>)
fun stopRendering()
fun setAspectRatio(width: Int, height: Int)

// Rendering state
val isRendering: StateFlow<Boolean>
val renderingStats: Flow<RenderStats>

RenderStats

data class RenderStats(
    val fps: Float,
    val droppedFrames: Int,
    val renderingLatency: Long
)

Usage Example

val surfaceView = findViewById<SurfaceView>(R.id.preview_surface)
val renderer = VideoPreviewRenderer(surfaceView)

// Start rendering video frames
lifecycleScope.launch {
    renderer.startRendering(videoCapture.videoFrames)
}

// Monitor rendering performance
renderer.renderingStats.collect { stats ->
    updateUI("FPS: ${stats.fps}, Dropped: ${stats.droppedFrames}")
}

CameraOverlayView

Manages camera overlay functionality with touch-based interaction.

Class Definition

class CameraOverlayView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr)

Public Interface

// Camera control
suspend fun startCamera(): Result<Boolean>
fun stopCamera()
val isCameraActive: StateFlow<Boolean>

// Overlay configuration
fun setPosition(position: OverlayPosition)
fun setSize(size: OverlaySize)
fun setVisibility(visible: Boolean)

// Touch interaction
var isDraggable: Boolean
var isResizable: Boolean

// Camera frames
val cameraFrames: Flow<Bitmap>

OverlayPosition

enum class OverlayPosition {
    TOP_LEFT,
    TOP_RIGHT,
    BOTTOM_LEFT,
    BOTTOM_RIGHT,
    CUSTOM
}

OverlaySize

enum class OverlaySize {
    SMALL,    // 15% of parent width
    MEDIUM,   // 25% of parent width
    LARGE,    // 35% of parent width
    CUSTOM
}

Usage Example

val cameraOverlay = findViewById<CameraOverlayView>(R.id.camera_overlay)

// Configure overlay
cameraOverlay.setPosition(OverlayPosition.TOP_RIGHT)
cameraOverlay.setSize(OverlaySize.MEDIUM)
cameraOverlay.isDraggable = true

// Start camera
lifecycleScope.launch {
    val result = cameraOverlay.startCamera()
    if (result.isSuccess) {
        // Camera overlay is now active
    }
}

StreamCompositor

Combines USB video and camera overlay into a single video stream.

Class Definition

class StreamCompositor

Public Interface

// Composition setup
fun setMainVideoSource(videoFlow: Flow<VideoFrame>)
fun setOverlaySource(overlayFlow: Flow<Bitmap>)
fun setOverlayConfiguration(config: OverlayConfig)

// Composite output
val compositeFrames: Flow<VideoFrame>
val compositionState: StateFlow<CompositionState>

// Composition control
suspend fun startComposition(): Result<Boolean>
fun stopComposition()

OverlayConfig

data class OverlayConfig(
    val position: OverlayPosition,
    val size: Size,
    val opacity: Float = 1.0f,
    val cornerRadius: Float = 0f
)

Usage Example

val compositor = StreamCompositor()

// Setup sources
compositor.setMainVideoSource(usbCapture.videoFrames)
compositor.setOverlaySource(cameraOverlay.cameraFrames)

// Configure overlay
val config = OverlayConfig(
    position = OverlayPosition.TOP_RIGHT,
    size = Size(320, 240),
    opacity = 0.9f
)
compositor.setOverlayConfiguration(config)

// Start composition
lifecycleScope.launch {
    compositor.startComposition()
    compositor.compositeFrames.collect { frame ->
        // Send to streaming
        rtmpStreamer.encodeFrame(frame)
    }
}

RtmpStreamer

Handles RTMP streaming and video encoding.

Class Definition

class RtmpStreamer

Public Interface

// Streaming configuration
data class StreamConfig(
    val rtmpUrl: String,
    val streamKey: String? = null,
    val bitrate: Int,
    val resolution: Resolution,
    val fps: Int
)

// Streaming control
suspend fun startStreaming(config: StreamConfig): Result<Boolean>
suspend fun stopStreaming()
fun encodeFrame(frame: VideoFrame)

// Streaming state
val streamingState: StateFlow<StreamingState>
val streamingStats: Flow<StreamingStats>

StreamingState

sealed class StreamingState {
    object Idle : StreamingState()
    object Connecting : StreamingState()
    object Streaming : StreamingState()
    object Reconnecting : StreamingState()
    data class Error(val message: String) : StreamingState()
}

StreamingStats

data class StreamingStats(
    val bitrate: Int,
    val fps: Float,
    val droppedFrames: Int,
    val connectionTime: Long
)

Usage Example

val rtmpStreamer = RtmpStreamer()

// Configure streaming
val config = StreamConfig(
    rtmpUrl = "rtmp://live.twitch.tv/live/",
    streamKey = "your_stream_key",
    bitrate = 2500,
    resolution = Resolution(1280, 720),
    fps = 30
)

// Start streaming
lifecycleScope.launch {
    val result = rtmpStreamer.startStreaming(config)
    if (result.isSuccess) {
        // Monitor streaming stats
        rtmpStreamer.streamingStats.collect { stats ->
            updateStreamingUI(stats)
        }
    }
}

MainActivity Integration

Example of how components work together in MainActivity:

Complete Setup

class MainActivity : AppCompatActivity() {
    private lateinit var usbCaptureManager: UsbCaptureManager
    private lateinit var videoRenderer: VideoPreviewRenderer
    private lateinit var cameraOverlay: CameraOverlayView
    private lateinit var streamCompositor: StreamCompositor
    private lateinit var rtmpStreamer: RtmpStreamer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupComponents()
        observeStates()
    }

    private fun setupComponents() {
        // Initialize all components
        usbCaptureManager = UsbCaptureManager(this, usbManager)
        videoRenderer = VideoPreviewRenderer(surfaceView)
        cameraOverlay = findViewById(R.id.camera_overlay)
        streamCompositor = StreamCompositor()
        rtmpStreamer = RtmpStreamer()

        // Connect components
        lifecycleScope.launch {
            // Setup video pipeline
            usbCaptureManager.connectionState.collect { state ->
                when (state) {
                    is ConnectionState.Connected -> {
                        setupVideoPipeline()
                    }
                }
            }
        }
    }

    private suspend fun setupVideoPipeline() {
        val videoCapture = UsbVideoCapture(connection, interface)

        // Start video capture
        videoCapture.startCapture(VideoFormat.YUV420)

        // Setup preview
        videoRenderer.startRendering(videoCapture.videoFrames)

        // Setup composition
        streamCompositor.setMainVideoSource(videoCapture.videoFrames)
        streamCompositor.setOverlaySource(cameraOverlay.cameraFrames)
        streamCompositor.startComposition()

        // Setup streaming
        streamCompositor.compositeFrames.collect { frame ->
            rtmpStreamer.encodeFrame(frame)
        }
    }
}

This architecture provides a clean separation of concerns while maintaining efficient data flow and state management throughout the application.