| | |
| | | package com.anyun.h264 |
| | | |
| | | import android.os.Bundle |
| | | import android.util.Log |
| | | import androidx.activity.ComponentActivity |
| | | import androidx.activity.compose.setContent |
| | | import androidx.activity.enableEdgeToEdge |
| | | import androidx.compose.foundation.layout.fillMaxSize |
| | | import androidx.compose.foundation.layout.padding |
| | | import androidx.compose.material3.Scaffold |
| | | import androidx.compose.material3.Text |
| | | import androidx.compose.runtime.Composable |
| | | import androidx.compose.foundation.layout.* |
| | | import androidx.compose.material3.* |
| | | import androidx.compose.runtime.* |
| | | import androidx.compose.ui.Alignment |
| | | import androidx.compose.ui.Modifier |
| | | import androidx.compose.ui.tooling.preview.Preview |
| | | import androidx.compose.ui.unit.dp |
| | | import com.anyun.h264.ui.theme.MyApplicationTheme |
| | | import java.io.File |
| | | |
| | | class MainActivity : ComponentActivity() { |
| | | private var h264Encoder: H264Encoder? = null |
| | | |
| | | override fun onCreate(savedInstanceState: Bundle?) { |
| | | super.onCreate(savedInstanceState) |
| | | enableEdgeToEdge() |
| | | |
| | | setContent { |
| | | var isRunning by remember { mutableStateOf(false) } |
| | | |
| | | MyApplicationTheme { |
| | | Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> |
| | | Greeting( |
| | | name = "Android", |
| | | modifier = Modifier.padding(innerPadding) |
| | | MainScreen( |
| | | modifier = Modifier.padding(innerPadding), |
| | | isRunning = isRunning, |
| | | onStartH264Click = { |
| | | val success = startH264Encoder() |
| | | if (success) { |
| | | isRunning = true |
| | | } |
| | | }, |
| | | onStopH264Click = { |
| | | stopH264Encoder() |
| | | isRunning = false |
| | | } |
| | | ) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | override fun onDestroy() { |
| | | super.onDestroy() |
| | | stopH264Encoder() |
| | | } |
| | | |
| | | private fun startH264Encoder(): Boolean { |
| | | if (h264Encoder != null) { |
| | | Log.w("MainActivity", "H264Encoder is already running") |
| | | return false |
| | | } |
| | | |
| | | try { |
| | | // 创建编码器 |
| | | h264Encoder = H264Encoder() |
| | | |
| | | // 设置编码参数 |
| | | h264Encoder?.setEncoderParams(640, 480, 25, 2000000) |
| | | |
| | | // 设置输出文件(可选) |
| | | val outputFile = File(getExternalFilesDir(null), "test.h264") |
| | | h264Encoder?.setOutputFile(outputFile.absolutePath) |
| | | h264Encoder?.setEnableFileOutput(true) // 启用文件输出 |
| | | |
| | | // 设置UDP服务器地址(可选) |
| | | h264Encoder?.setServerAddress("192.168.1.100", 8888) |
| | | h264Encoder?.setProtocolParams("123456789012", 1) |
| | | |
| | | // 初始化并启动 |
| | | val cameraIdRange = intArrayOf(1, 2) |
| | | val resolution = intArrayOf(640, 480) |
| | | |
| | | if (h264Encoder?.initialize(cameraIdRange, null, resolution, false) == true) { |
| | | h264Encoder?.start() |
| | | Log.d("MainActivity", "H264Encoder started successfully") |
| | | Log.d("MainActivity", "Output file: ${outputFile.absolutePath}") |
| | | return true |
| | | } else { |
| | | Log.e("MainActivity", "Failed to initialize H264Encoder") |
| | | h264Encoder = null |
| | | return false |
| | | } |
| | | } catch (e: Exception) { |
| | | Log.e("MainActivity", "Failed to start H264Encoder", e) |
| | | h264Encoder = null |
| | | return false |
| | | } |
| | | } |
| | | |
| | | private fun stopH264Encoder() { |
| | | h264Encoder?.let { encoder -> |
| | | try { |
| | | encoder.stop() |
| | | Log.d("MainActivity", "H264Encoder stopped") |
| | | } catch (e: Exception) { |
| | | Log.e("MainActivity", "Failed to stop H264Encoder", e) |
| | | } |
| | | h264Encoder = null |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Composable |
| | | fun Greeting(name: String, modifier: Modifier = Modifier) { |
| | | Text( |
| | | text = "Hello $name!", |
| | | fun MainScreen( |
| | | modifier: Modifier = Modifier, |
| | | isRunning: Boolean, |
| | | onStartH264Click: () -> Unit, |
| | | onStopH264Click: () -> Unit |
| | | ) { |
| | | Column( |
| | | modifier = modifier |
| | | ) |
| | | } |
| | | |
| | | @Preview(showBackground = true) |
| | | @Composable |
| | | fun GreetingPreview() { |
| | | MyApplicationTheme { |
| | | Greeting("Android") |
| | | .fillMaxSize() |
| | | .padding(16.dp), |
| | | horizontalAlignment = Alignment.CenterHorizontally, |
| | | verticalArrangement = Arrangement.Center |
| | | ) { |
| | | Text( |
| | | text = "H264 编码器", |
| | | style = MaterialTheme.typography.headlineMedium |
| | | ) |
| | | |
| | | Spacer(modifier = Modifier.height(32.dp)) |
| | | |
| | | Button( |
| | | onClick = onStartH264Click, |
| | | enabled = !isRunning, |
| | | modifier = Modifier |
| | | .fillMaxWidth() |
| | | .height(56.dp) |
| | | ) { |
| | | Text("启动 H264") |
| | | } |
| | | |
| | | Spacer(modifier = Modifier.height(16.dp)) |
| | | |
| | | Button( |
| | | onClick = onStopH264Click, |
| | | enabled = isRunning, |
| | | modifier = Modifier |
| | | .fillMaxWidth() |
| | | .height(56.dp), |
| | | colors = ButtonDefaults.buttonColors( |
| | | containerColor = MaterialTheme.colorScheme.error |
| | | ) |
| | | ) { |
| | | Text("停止 H264") |
| | | } |
| | | |
| | | Spacer(modifier = Modifier.height(32.dp)) |
| | | |
| | | if (isRunning) { |
| | | Text( |
| | | text = "编码器运行中...", |
| | | style = MaterialTheme.typography.bodyMedium, |
| | | color = MaterialTheme.colorScheme.primary |
| | | ) |
| | | } |
| | | } |
| | | } |