Add device orientation information to header information,Simplified encoder package, added session package

This commit is contained in:
gz0119 2025-03-13 20:09:09 +08:00
parent a98e50078a
commit 666758d680
6 changed files with 63 additions and 22 deletions

View file

@ -63,17 +63,26 @@ sc_demuxer_recv_codec_id(struct sc_demuxer *demuxer, uint32_t *codec_id) {
return true;
}
static void
handle_video_session_packet(uint8_t *data){
int width = sc_read32be(data + 1);
int height = sc_read32be(data + 5);
bool isFlip = data[9] == 1;
int direction = (data[10] == (uint8_t)1 ? 2 : 0) + (data[11] == (uint8_t)1 ? 1 : 0);
LOGI("Width=%d, Height=%d, Flip=%s, Direction=%d", width, height, isFlip ? "True" : "False", direction);
}
static bool
sc_demuxer_recv_video_size(struct sc_demuxer *demuxer, uint32_t *width,
uint32_t *height) {
uint8_t data[8];
ssize_t r = net_recv_all(demuxer->socket, data, 8);
if (r < 8) {
uint8_t data[12];
ssize_t r = net_recv_all(demuxer->socket, data, 12);
if (r < 12) {
return false;
}
*width = sc_read32be(data);
*height = sc_read32be(data + 4);
*width = sc_read32be(data + 1);
*height = sc_read32be(data + 5);
handle_video_session_packet(data);
return true;
}
@ -104,6 +113,11 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
if (r < SC_PACKET_HEADER_SIZE) {
return false;
}
if(header[0] == 0xff){
handle_video_session_packet(header);
return true;
}
uint64_t pts_flags = sc_read64be(header);
uint32_t len = sc_read32be(&header[8]);
@ -218,11 +232,11 @@ run_demuxer(void *data) {
LOGE("Demuxer '%s': could not open codec", demuxer->name);
goto finally_free_context;
}
if (!sc_packet_source_sinks_open(&demuxer->packet_source, codec_ctx)) {
goto finally_free_context;
}
// Config packets must be merged with the next non-config packet only for
// H.26x
bool must_merge_config_packet = raw_codec_id == SC_CODEC_ID_H264

View file

@ -258,8 +258,7 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
struct sc_screen *screen = DOWNCAST(sink);
if (ctx->width <= 0 || ctx->width > 0xFFFF
|| ctx->height <= 0 || ctx->height > 0xFFFF) {
if (ctx->width <= 0 || ctx->width > 0xFFFF || ctx->height <= 0 || ctx->height > 0xFFFF) {
LOGE("Invalid video size: %dx%d", ctx->width, ctx->height);
return false;
}

View file

@ -152,7 +152,7 @@ public final class Server {
surfaceCapture = new NewDisplayCapture(controller, options);
} else {
assert options.getDisplayId() != Device.DISPLAY_ID_NONE;
surfaceCapture = new ScreenCapture(controller, options);
surfaceCapture = new ScreenCapture(controller, videoStreamer, options);
}
} else {
surfaceCapture = new CameraCapture(options);

View file

@ -8,6 +8,7 @@ import android.media.MediaCodec;
import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
@ -16,6 +17,7 @@ public final class Streamer {
private static final long PACKET_FLAG_CONFIG = 1L << 63;
private static final long PACKET_FLAG_KEY_FRAME = 1L << 62;
private static final long PACKET_FLAG_VIDEO_SESSION = 1L << 61;
private final FileDescriptor fd;
private final Codec codec;
@ -44,12 +46,24 @@ public final class Streamer {
}
}
public void writeVideoHeader(Size videoSize) throws IOException {
public void writeVideoHeader() throws IOException {
if (sendCodecMeta) {
ByteBuffer buffer = ByteBuffer.allocate(12);
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(codec.getId());
buffer.flip();
IO.writeFully(fd, buffer);
}
}
public void writeVideoSession(Size videoSize, boolean isFlip, int rotation) throws IOException{
if(sendCodecMeta){
ByteBuffer buffer = ByteBuffer.allocate(12);
buffer.put((byte) 0xff);
buffer.putInt(videoSize.getWidth());
buffer.putInt(videoSize.getHeight());
rotation = rotation * 90;
buffer.put((byte) (isFlip ? 1 : 0));
buffer.put((byte) (rotation >= 180 ? 1 : 0));
buffer.put((byte) (rotation >= 90 ? 1 : 0));
buffer.flip();
IO.writeFully(fd, buffer);
}

View file

@ -7,6 +7,7 @@ import com.genymobile.scrcpy.device.ConfigurationException;
import com.genymobile.scrcpy.device.Device;
import com.genymobile.scrcpy.device.DisplayInfo;
import com.genymobile.scrcpy.device.Orientation;
import com.genymobile.scrcpy.device.Streamer;
import com.genymobile.scrcpy.device.Size;
import com.genymobile.scrcpy.opengl.AffineOpenGLFilter;
import com.genymobile.scrcpy.opengl.OpenGLFilter;
@ -34,6 +35,7 @@ public class ScreenCapture extends SurfaceCapture {
private Orientation.Lock captureOrientationLock;
private Orientation captureOrientation;
private final float angle;
private final Streamer streamer;
private DisplayInfo displayInfo;
private Size videoSize;
@ -46,7 +48,7 @@ public class ScreenCapture extends SurfaceCapture {
private AffineMatrix transform;
private OpenGLRunner glRunner;
public ScreenCapture(VirtualDisplayListener vdListener, Options options) {
public ScreenCapture(VirtualDisplayListener vdListener, Streamer streamer, Options options) {
this.vdListener = vdListener;
this.displayId = options.getDisplayId();
assert displayId != Device.DISPLAY_ID_NONE;
@ -57,6 +59,7 @@ public class ScreenCapture extends SurfaceCapture {
assert captureOrientationLock != null;
assert captureOrientation != null;
this.angle = options.getAngle();
this.streamer = streamer;
}
@Override
@ -77,27 +80,38 @@ public class ScreenCapture extends SurfaceCapture {
}
Size displaySize = displayInfo.getSize();
displaySizeMonitor.setSessionInfo(displaySize, displayInfo.getRotation());
int displayRotation = displayInfo.getRotation();
displaySizeMonitor.setSessionInfo(displaySize, displayRotation);
if (captureOrientationLock == Orientation.Lock.LockedInitial) {
// The user requested to lock the video orientation to the current orientation
captureOrientationLock = Orientation.Lock.LockedValue;
captureOrientation = Orientation.fromRotation(displayInfo.getRotation());
captureOrientation = Orientation.fromRotation(displayRotation);
}
VideoFilter filter = new VideoFilter(displaySize);
if (crop != null) {
boolean transposed = (displayInfo.getRotation() % 2) != 0;
boolean transposed = (displayRotation % 2) != 0;
filter.addCrop(crop, transposed);
}
boolean locked = captureOrientationLock != Orientation.Lock.Unlocked;
filter.addOrientation(displayInfo.getRotation(), locked, captureOrientation);
filter.addOrientation(displayRotation, locked, captureOrientation);
filter.addAngle(angle);
transform = filter.getInverseTransform();
videoSize = filter.getOutputSize().limit(maxSize).round8();
try {
boolean isFlipped = captureOrientation.isFlipped();
streamer.writeVideoSession(videoSize, isFlipped, displayRotation);
} catch (Exception e) {
}
// Ln.i("@@@@@@@"+(transform != null ? transform.toString():"Null"));
// Ln.i("===="+captureOrientation.isFlipped()+"=="+captureOrientation.getRotation());
// Ln.i("===="+displayInfo.getRotation()+"=="+videoSize.getWidth()+"=="+videoSize.getHeight()+"=="+locked+"==============");
}
@Override

View file

@ -74,13 +74,13 @@ public class SurfaceEncoder implements AsyncProcessor {
boolean headerWritten = false;
do {
if (!headerWritten) {
streamer.writeVideoHeader();
headerWritten = true;
}
reset.consumeReset(); // If a capture reset was requested, it is implicitly fulfilled
capture.prepare();
Size size = capture.getSize();
if (!headerWritten) {
streamer.writeVideoHeader(size);
headerWritten = true;
}
format.setInteger(MediaFormat.KEY_WIDTH, size.getWidth());
format.setInteger(MediaFormat.KEY_HEIGHT, size.getHeight());