Skip to content

Commit

Permalink
更新V10.4
Browse files Browse the repository at this point in the history
修复声音传递失效问题
修复连接失败导致崩溃问题
完善错误提示
尝试优化视频延迟
  • Loading branch information
mingzhixian committed Jun 18, 2023
1 parent d656093 commit 1ea3426
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 30 deletions.
4 changes: 2 additions & 2 deletions scrcpy_android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId "top.saymzx.scrcpy.android"
minSdk 23
targetSdk 33
versionCode 103
versionName "10.3"
versionCode 104
versionName "10.4"
resConfigs "zh"
resConfigs "xhdpi"
ndk {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.media.*
import android.net.Uri
import android.os.*
import android.provider.Settings
import android.util.Log
import android.view.*
import android.view.KeyEvent.*
import android.view.MotionEvent.*
Expand All @@ -20,7 +19,6 @@ import androidx.lifecycle.ViewModelStoreOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.Request
Expand Down Expand Up @@ -152,7 +150,7 @@ class MainActivity : Activity(), ViewModelStoreOwner {
findViewById<TextView>(R.id.add_device).setOnLongClickListener {
for (i in appData.devices) {
i.status = -1
i.scrcpy.stop()
i.scrcpy.stop("强行停止")
}
Toast.makeText(this, "已强制清理", Toast.LENGTH_SHORT).show()
return@setOnLongClickListener true
Expand Down Expand Up @@ -239,7 +237,7 @@ class MainActivity : Activity(), ViewModelStoreOwner {
override fun onReceive(context: Context?, intent: Intent?) {
// 取消通知
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(1)
for (i in appData.devices) if (i.status >= 0) i.scrcpy.stop()
for (i in appData.devices) if (i.status >= 0) i.scrcpy.stop("停止投屏")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import android.media.AudioTrack
import android.media.AudioTrack.WRITE_NON_BLOCKING
import android.media.MediaCodec
import android.media.MediaCodec.Callback
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.media.audiofx.LoudnessEnhancer
import android.os.Build
import android.util.Base64
import android.util.Log
import android.view.SurfaceView
Expand Down Expand Up @@ -69,7 +71,7 @@ class Scrcpy(private val device: Device) {
device.status = 0
// 显示加载中
appData.showLoading("连接中...", true) {
stop()
stop("用户停止")
}
appData.loadingDialog.show()
scrcpyScope.launch {
Expand All @@ -82,6 +84,10 @@ class Scrcpy(private val device: Device) {
sendServer()
// 转发端口
tcpForward()
} catch (e: Exception) {
stop("连接错误", e)
}
try {
// 配置视频解码
setVideoDecodec()
// 配置音频解码
Expand All @@ -93,14 +99,14 @@ class Scrcpy(private val device: Device) {
// 设置被控端熄屏(默认投屏后熄屏)
setPowerOff()
} catch (e: Exception) {
stop(e)
stop("启动错误", e)
}
// 视频解码输入
Thread {
try {
decodeInput("video")
} catch (e: Exception) {
stop(e)
stop("投屏停止", e)
}
}.start()
// 音频解码输入
Expand All @@ -109,7 +115,7 @@ class Scrcpy(private val device: Device) {
try {
decodeInput("audio")
} catch (e: Exception) {
stop(e)
stop("投屏停止", e)
}
}.start()
}
Expand All @@ -118,19 +124,27 @@ class Scrcpy(private val device: Device) {
try {
setControlInput()
} catch (e: Exception) {
stop(e)
stop("投屏停止", e)
}
}.start()
}
}

// 停止投屏
fun stop(e: Exception = Exception("停止")) {
fun stop(scrcpyError: String, e: Exception? = null) {
// 防止多次调用
if (device.status == -1) return
val oldStatus = device.status
device.status = -1
Log.e("Scrcpy", e.toString())
if (device.status == 0) appData.loadingDialog.cancel()
appData.mainScope.launch {
withContext(Dispatchers.Main) {
Toast.makeText(appData.main, scrcpyError, Toast.LENGTH_SHORT).show()
if (e != null)
Toast.makeText(appData.main, e.toString(), Toast.LENGTH_SHORT).show()
}
}
Log.e("Scrcpy", "$scrcpyError---${e?.toString() ?: ""}")
if (oldStatus == 0) appData.loadingDialog.cancel()
scrcpyScope.cancel()
appData.mainScope.launch {
try {
Expand All @@ -141,7 +155,10 @@ class Scrcpy(private val device: Device) {
} catch (_: Exception) {
}
}
floatVideo.hide()
try {
floatVideo.hide()
} catch (_: Exception) {
}
try {
if (canAudio) {
loudnessEnhancer.release()
Expand All @@ -157,10 +174,13 @@ class Scrcpy(private val device: Device) {
videoDecodec.release()
} catch (_: Exception) {
}
videoStream.close()
audioStream.close()
controlOutStream.close()
controlInStream.close()
try {
videoStream.close()
audioStream.close()
controlOutStream.close()
controlInStream.close()
} catch (_: Exception) {
}
}

// 发送server
Expand All @@ -176,7 +196,6 @@ class Scrcpy(private val device: Device) {
runAdbCmd("ps -ef | grep scrcpy | grep -v grep | grep -E \"^[a-z]+ +[0-9]+\" -o | grep -E \"[0-9]+\" -o | xargs kill -9")
// 快速启动
if (runAdbCmd(" ls -l /data/local/tmp/scrcpy_server${appData.versionCode}.jar ").contains("No such file or directory")) {
runAdbCmd("rm /data/local/tmp/serverBase64")
runAdbCmd("rm /data/local/tmp/scrcpy_server*")
val serverFileBase64 = Base64.encodeToString(withContext(Dispatchers.IO) {
val server = appData.main.resources.openRawResource(R.raw.scrcpy_server)
Expand All @@ -185,8 +204,8 @@ class Scrcpy(private val device: Device) {
server.close()
buffer
}, 2)
runAdbCmd("echo $serverFileBase64 >> /data/local/tmp/serverBase64\n")
runAdbCmd("base64 -d < /data/local/tmp/serverBase64 > /data/local/tmp/scrcpy_server${appData.versionCode}.jar && rm /data/local/tmp/serverBase64")
runAdbCmd("echo $serverFileBase64 >> /data/local/tmp/scrcpy_server_base64\n")
runAdbCmd("base64 -d < /data/local/tmp/scrcpy_server_base64 > /data/local/tmp/scrcpy_server${appData.versionCode}.jar && rm /data/local/tmp/scrcpy_server_base64")
}
runAdbCmd("CLASSPATH=/data/local/tmp/scrcpy_server${appData.versionCode}.jar app_process / com.genymobile.scrcpy.Server 2.0 video_codec=${device.videoCodec} max_size=${device.maxSize} video_bit_rate=${device.videoBit} max_fps=${device.fps} > /dev/null 2>&1 &")
}
Expand Down Expand Up @@ -246,6 +265,13 @@ class Scrcpy(private val device: Device) {
val csd1 = withContext(Dispatchers.IO) { readFrame(videoStream) }
mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(csd0))
mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd1))
// 配置低延迟解码
val codeInfo = videoDecodec.codecInfo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (codeInfo.getCapabilitiesForType(codecMime)
.isFeatureSupported(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency)
) mediaFormat.setInteger(MediaFormat.KEY_LOW_LATENCY, 1)
}
// 配置解码器
videoDecodec.configure(
mediaFormat,
Expand Down Expand Up @@ -274,8 +300,8 @@ class Scrcpy(private val device: Device) {
)
}
decodec.releaseOutputBuffer(outIndex, true)
} catch (e: IllegalStateException) {
stop(e)
} catch (e: Exception) {
stop("投屏停止", e)
}
}

Expand Down Expand Up @@ -341,12 +367,14 @@ class Scrcpy(private val device: Device) {
checkClipBoard()
}
try {
val byteArray = ByteArray(bufferInfo.size)
decodec.getOutputBuffer(outIndex)!!.get(byteArray)
audioTrack.write(byteArray, bufferInfo.size, WRITE_NON_BLOCKING)
audioTrack.write(
decodec.getOutputBuffer(outIndex)!!,
bufferInfo.size,
WRITE_NON_BLOCKING
)
decodec.releaseOutputBuffer(outIndex, false)
} catch (e: IllegalStateException) {
stop(e)
} catch (e: Exception) {
stop("投屏停止", e)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,16 @@ public void streamScreen() throws IOException, ConfigurationException {
Rect videoRect = screenInfo.getVideoSize().toRect();
format.setInteger(MediaFormat.KEY_WIDTH, videoRect.width());
format.setInteger(MediaFormat.KEY_HEIGHT, videoRect.height());
if (mediaCodec.getCodecInfo().getCapabilitiesForType(codec.getMimeType()).getEncoderCapabilities().isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) {
MediaCodecInfo codeInfo = mediaCodec.getCodecInfo();
if (codeInfo.getCapabilitiesForType(codec.getMimeType()).getEncoderCapabilities().isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) {
format.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
}
// 使用基线编码标准,会造成快速运动时模糊
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
// format.setInteger(
// "profile",
// MediaCodecInfo.CodecProfileLevel.AVCProfileConstrainedBaseline);
// }
Surface surface = null;
try {
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Expand Down

0 comments on commit 1ea3426

Please sign in to comment.