fix: 修复自编码模式黑屏问题
- 调整包序号过期检查逻辑,避免同一帧分片被误删 - 适配 Android 14,在创建 VirtualDisplay 前注册 MediaProjection.Callback - 启动后检查编码器实际运行状态,失败时进行清理
This commit is contained in:
@@ -476,6 +476,13 @@ public class ScreenCaptureService extends Service {
|
||||
}
|
||||
});
|
||||
selfEncoder.start();
|
||||
// start() 内部捕获异常后 running 仍为 false,需据此判断真实启动结果,
|
||||
// 否则会误报 SELF_CODEC 模式已生效而实际无任何画面(黑屏)。
|
||||
if (!selfEncoder.isRunning()) {
|
||||
Log.e(TAG, "self codec encoder failed to start, cleaning up");
|
||||
stopSelfCodecEncoder();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public class SelfCodecEncoder {
|
||||
private MediaCodec encoder;
|
||||
private Surface inputSurface;
|
||||
private VirtualDisplay virtualDisplay;
|
||||
private MediaProjection.Callback projectionCallback;
|
||||
private boolean running = false;
|
||||
private int frameSeq = 0;
|
||||
private final Object sendLock = new Object();
|
||||
@@ -88,6 +89,20 @@ public class SelfCodecEncoder {
|
||||
inputSurface = encoder.createInputSurface();
|
||||
encoder.start();
|
||||
|
||||
// Android 14+ (API 34) 强制要求:在 createVirtualDisplay 之前必须先注册
|
||||
// MediaProjection.Callback,否则会抛
|
||||
// IllegalStateException("Must register a callback before starting capture..."),
|
||||
// 导致自编码模式无法启动、控制端黑屏。onStop 时释放资源。
|
||||
projectionCallback = new MediaProjection.Callback() {
|
||||
@Override
|
||||
public void onStop() {
|
||||
Log.e(TAG, "MediaProjection stopped, releasing encoder");
|
||||
release();
|
||||
if (callback != null) callback.onEncoderError("MediaProjection stopped");
|
||||
}
|
||||
};
|
||||
mediaProjection.registerCallback(projectionCallback, null);
|
||||
|
||||
virtualDisplay = mediaProjection.createVirtualDisplay(
|
||||
"SelfCodec", width, height, dpi,
|
||||
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, inputSurface, null, null);
|
||||
@@ -246,6 +261,11 @@ public class SelfCodecEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
/** 返回编码器是否正在运行(供上层判断启动结果)。 */
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/** 即时请求一个关键帧(强求 IDR)。 */
|
||||
public void requestKeyFrame() {
|
||||
if (encoder == null) return;
|
||||
@@ -260,6 +280,13 @@ public class SelfCodecEncoder {
|
||||
|
||||
public void release() {
|
||||
running = false;
|
||||
if (mediaProjection != null && projectionCallback != null) {
|
||||
try {
|
||||
mediaProjection.unregisterCallback(projectionCallback);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
projectionCallback = null;
|
||||
}
|
||||
if (virtualDisplay != null) {
|
||||
try {
|
||||
virtualDisplay.release();
|
||||
|
||||
Reference in New Issue
Block a user