2023-05-14 07:48:34 +00:00
|
|
|
import typing as t
|
|
|
|
|
|
|
|
import module.device.method.scrcpy.const as const
|
|
|
|
|
|
|
|
|
|
|
|
class ScrcpyOptions:
|
2023-06-16 13:43:11 +00:00
|
|
|
frame_rate = 10
|
2023-05-14 07:48:34 +00:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def codec_options(cls) -> str:
|
|
|
|
"""
|
|
|
|
Custom codec options passing through scrcpy.
|
|
|
|
https://developer.android.com/reference/android/media/MediaFormat
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
key_profile=1,key_level=4096,...
|
|
|
|
"""
|
|
|
|
options = dict(
|
|
|
|
# H.264 profile and level
|
|
|
|
# https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel
|
|
|
|
# Baseline, which only has I/P frames
|
|
|
|
key_profile=1,
|
|
|
|
# Level 4.1, for 1280x720@30fps
|
|
|
|
key_level=4096,
|
|
|
|
# Max quality
|
|
|
|
key_quality=100,
|
|
|
|
# https://developer.android.com/reference/android/media/MediaCodecInfo.EncoderCapabilities
|
|
|
|
# Constant quality
|
|
|
|
key_bitrate_mode=0,
|
|
|
|
# A zero value means a stream containing all key frames is requested.
|
|
|
|
key_i_frame_interval=0,
|
|
|
|
# https://developer.android.com/reference/android/media/MediaCodecInfo.CodecCapabilities
|
|
|
|
# COLOR_Format24bitBGR888
|
|
|
|
key_color_format=12,
|
|
|
|
# The same as output frame rate to lower CPU consumption
|
|
|
|
key_capture_rate=cls.frame_rate,
|
|
|
|
# 20Mbps, the maximum output bitrate of scrcpy
|
|
|
|
key_bit_rate=20000000,
|
|
|
|
)
|
|
|
|
return ','.join([f'{k}={v}' for k, v in options.items()])
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def arguments(cls) -> t.List[str]:
|
|
|
|
"""
|
|
|
|
https://github.com/Genymobile/scrcpy/blob/master/server/src/main/java/com/genymobile/scrcpy/Server.java
|
|
|
|
https://github.com/Genymobile/scrcpy/blob/master/server/src/main/java/com/genymobile/scrcpy/Options.java
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
['log_level=info', 'max_size=1280', ...]
|
|
|
|
"""
|
|
|
|
options = [
|
|
|
|
'log_level=info',
|
|
|
|
'max_size=1280',
|
|
|
|
# 20Mbps, the maximum output bitrate of scrcpy
|
|
|
|
# If a higher value is set, scrcpy fallback to 8Mbps default.
|
|
|
|
'bit_rate=20000000',
|
|
|
|
# Screenshot time cost <= 300ms is enough for human speed.
|
|
|
|
f'max_fps={cls.frame_rate}',
|
|
|
|
# No orientation lock
|
|
|
|
f'lock_video_orientation={const.LOCK_SCREEN_ORIENTATION_UNLOCKED}',
|
|
|
|
# Always true
|
|
|
|
'tunnel_forward=true',
|
|
|
|
# Always true for controlling via scrcpy
|
|
|
|
'control=true',
|
|
|
|
# Default to 0
|
|
|
|
'display_id=0',
|
|
|
|
# Useless, always false
|
|
|
|
'show_touches=false',
|
|
|
|
# Not determined, leave it as default
|
|
|
|
'stay_awake=false',
|
|
|
|
# Encoder name
|
|
|
|
# Should in [
|
|
|
|
# "OMX.google.h264.encoder",
|
|
|
|
# "OMX.qcom.video.encoder.avc",
|
|
|
|
# "c2.qti.avc.encoder",
|
|
|
|
# "c2.android.avc.encoder",
|
|
|
|
# ]
|
|
|
|
# Empty value, let scrcpy to decide
|
|
|
|
# 'encoder_name=',
|
|
|
|
# Codec options
|
|
|
|
f'codec_options={cls.codec_options()}',
|
|
|
|
# Useless, always false
|
|
|
|
'power_off_on_close=false',
|
|
|
|
'clipboard_autosync=false',
|
|
|
|
'downsize_on_error=false',
|
|
|
|
]
|
|
|
|
return options
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def command_v125(cls, jar_path='/data/local/tmp/scrcpy-server.jar') -> t.List[str]:
|
|
|
|
"""
|
|
|
|
Generate the commands to run scrcpy.
|
|
|
|
"""
|
|
|
|
commands = [
|
|
|
|
f'CLASSPATH={jar_path}',
|
|
|
|
'app_process',
|
|
|
|
'/',
|
|
|
|
'com.genymobile.scrcpy.Server',
|
|
|
|
'1.25',
|
|
|
|
]
|
|
|
|
commands += cls.arguments()
|
|
|
|
return commands
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def command_v120(cls, jar_path='/data/local/tmp/scrcpy-server.jar') -> t.List[str]:
|
|
|
|
commands = [
|
|
|
|
f"CLASSPATH={jar_path}",
|
|
|
|
"app_process",
|
|
|
|
"/",
|
|
|
|
"com.genymobile.scrcpy.Server",
|
|
|
|
"1.20", # Scrcpy server version
|
|
|
|
"info", # Log level: info, verbose...
|
|
|
|
f"1280", # Max screen width (long side)
|
|
|
|
f"20000000", # Bitrate of video
|
|
|
|
f"{cls.frame_rate}", # Max frame per second
|
|
|
|
f"{const.LOCK_SCREEN_ORIENTATION_UNLOCKED}", # Lock screen orientation: LOCK_SCREEN_ORIENTATION
|
|
|
|
"true", # Tunnel forward
|
|
|
|
"-", # Crop screen
|
|
|
|
"false", # Send frame rate to client
|
|
|
|
"true", # Control enabled
|
|
|
|
"0", # Display id
|
|
|
|
"false", # Show touches
|
|
|
|
"false", # Stay awake
|
|
|
|
cls.codec_options(), # Codec (video encoding) options
|
|
|
|
"-", # Encoder name
|
|
|
|
"false", # Power off screen after server closed
|
|
|
|
]
|
|
|
|
return commands
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
print(' '.join(ScrcpyOptions.command_v120()))
|