kvarenzn / phisap

[deprecated] [for android] Semi-automatic player for the rhythm game "Phigros"
174 stars 38 forks source link

[兼容bug]特定分辨率下scrcpy-server不正常工作(含解决方案) #14

Open luckylaiCN opened 2 years ago

luckylaiCN commented 2 years ago

此处直接调用control.py

PS D:\project\git\phisap> python .\control.py
scrcpy-server-v1.22: 1 file pushed. 0.6 MB/s (40955 bytes in 0.067s)
tap 0
Exception in thread Thread-1:
Exception in thread Thread-2:
Traceback (most recent call last):
  File "D:\python39\lib\threading.py", line 973, in _bootstrap_inner
Traceback (most recent call last):
  File "D:\python39\lib\threading.py", line 973, in _bootstrap_inner
    self.run()
  File "D:\python39\lib\threading.py", line 910, in run
    self.run()
  File "D:\python39\lib\threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "D:\project\git\phisap\control.py", line 58, in ctrlmsg_receiver
    self._target(*self._args, **self._kwargs)
  File "D:\project\git\phisap\control.py", line 48, in collector
    size, = struct.unpack('!I', self.control_socket.recv(4))
struct.error: unpack requires a buffer of 4 bytes
    pts, size = struct.unpack('!qI', header)
struct.error: unpack requires a buffer of 12 bytes
[server] ERROR: Exception on thread Thread[main,5,main]
android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:2023)
        at android.media.MediaCodec.configure(MediaCodec.java:1951)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:274)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:94)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:73)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:100)
        at com.genymobile.scrcpy.Server.main(Server.java:326)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:359)
tap 1
tap 2
Traceback (most recent call last):
  File "D:\project\git\phisap\control.py", line 105, in <module>
    ctl.touch_down(200, 200, pointer_id=ids)
  File "D:\project\git\phisap\control.py", line 81, in touch_down
    self.control_socket.send(struct.pack('!bbQiiHHHI', 2, 0, pointer_id, x, y, *self.device_size, pressure, 1))
ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。

原因:scrcpy对特定分辨率的设备不兼容。使用scrcpy编译的win64exe程序时的会同样出现问题

C:\Users\xxx\Downloads\scrcpy-win64-v1.22 (2)>scrcpy.exe
scrcpy 1.22 <https://github.com/Genymobile/scrcpy>
C:\Users\xxx\Downloads\scrcpy-win64-v1.22 (2)\scrcpy-server: 1 file pushed. 0.9 MB/s (40955 bytes in 0.044s)
[server] INFO: Device: HUAWEI AQM-AL10 (Android 10)
[server] ERROR: Exception on thread Thread[main,5,main]
android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:2023)
        at android.media.MediaCodec.configure(MediaCodec.java:1951)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:274)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:94)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:73)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:100)
        at com.genymobile.scrcpy.Server.main(Server.java:326)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:359)
INFO: Renderer: direct3d
INFO: Initial texture: 1080x2400
WARN: Device disconnected

对于scrcpy-server使用app_process时的解决方案:

/control.py # DeviceController.__init__


self.server_process = subprocess.Popen(  # line 26
            ['adb', 'shell', 'CLASSPATH=/data/local/tmp/scrcpy-server.jar', 'app_process', '/',
             'com.genymobile.scrcpy.Server',
             server_version,
             'log_level=warn',
             'bit_rate=8000000',
             'clipboard_autosync=false',
             'max_size=1920'  # + 在此处添加max_size参数。对于本机测试1920、1024可行。scrcpy官方给出的issue中其中一个是给予了1024
             ])
self.real_height,self.real_width = tuple(map(int,os.popen("adb shell wm size").read().split()[-1].split('x'))) # 获取真正的高和宽度

/control.py #DeviceController.touch_down method

x = x / self.real_width * self.device_size[0]
y = y / self.real_height * self.device_size[1]
x,y = int(x),int(y)

此处是将真实分辨率下的x,y坐标放缩为以scrcpy处理时的x,y坐标(同样touch_up touch_move也应该处理)

由于scrcpy内部的设计,在 width, height = struct.unpack('!HH', self.video_socket.recv(4))(line 62)中获取到的分辨率为处理的分辨率而不是真实分辨率(在处理分辨率和真实分辨率不同的情况下)。

而且很莫名其妙的在发送socket的时候是必须按照服务端处理的size,也就是说如果手机真实分辨率和处理分辨率不同,如果发送socket时发送的是真实分辨率而不是处理分辨率的话,服务端会选择ignore,并且给出warn。

PS: 对于命令行scrcpy直接调用时就是传递-m(--max-size)参数: For example scrcpy.exe -m 1920

I hope my advice will be of great help(不是

luckylaiCN commented 2 years ago

看了 #2 有可能也是一个问题

luckylaiCN commented 2 years ago

环境: python 3.9 (非开发时同版本环境) scrcpy-server-v1.12(newest release) windows 10 x64 HUAWEI AQM-AL10 (Android 10) Adb 1.0.40 (Version 4986621) (wlan connect)

kvarenzn commented 2 years ago

我去,是大佬,太强了 不知您是否方便提供一下那个scrcpy issue的链接?我学习一下。

看了#2有可能也是一个问题

由于那个issue没有提供进一步的信息,所以我确实不清楚是什么情况

scrcpy-server-v1.12

您指的是v1.22?

HUAWEI AQM-AL10

不好意思,对华为系列产品不太了解,请问这个是否指荣耀Play4T Pro?(如果是的话,我看这个分辨率也就2400x1080,应该也没啥特殊的啊)

luckylaiCN commented 2 years ago

我去,是大佬,太强了 不知您是否方便提供一下那个scrcpy issue的链接?我学习一下。

(其实issue也没写清楚)是这样的,最近有研究相关自动化操作,用到scrcpy,然后我的手机就出现0xfffffc0e错误,查了一下issue,发现#2571是比较好的解决办法,其它的没有实际操作,或许可行,但是好像像后面FAQ中给出的建议还有是换encoder,好像不好操作(主要是懒),所以就选择前者设定max-size。(还有我不是大佬啊喂,就是喜欢搞些小东西而已) 您指的是v1.22?

sorry是的,打错了

不好意思,对华为系列产品不太了解,请问这个是否指荣耀Play4T Pro?(如果是的话,我看这个分辨率也就2400x1080,应该也没啥特殊的啊)

是的,但是,scrcpy就是处 理 不 了默认分辨率(没错如果是2400他就会Error 0xfffffc0e),要强行打回一个较小的能处理的值。我也不理解,只能说这个可能要向scrcpy交issue了。

还有就是您repo的热度高了呢,还是要小心~像我一样~的yyw( (虽然我不觉得yyw有这技术配置这些玩意,所以建议开发的时候留点门槛)

至于其它分辨率不清楚,可能要靠模拟器做兼容测试。我给出的解决方案已经在我本机实现兼容了

(当然有部分是写issue的时候脚扣的,有bug不奇怪[bushi])

luckylaiCN commented 2 years ago

还有一个比较大的痛点就是scrcpy由于本身是内置录屏的,所以性能消耗特别大,电量蹭蹭蹭往下掉(

kvarenzn commented 2 years ago

但是好像像后面FAQ中给出的建议还有是换encoder

换encoder或许不需要换算屏幕坐标,不过不清楚您的设备上的其他encoder是否支持默认分辨率的编码。如果不行的话就只能启用坐标换算了。

至于其它分辨率不清楚,可能要靠模拟器做兼容测试

兼容测试是什么,我这都靠用户做兼容测试(不是

还有就是您repo的热度高了呢

我也不知道为啥最近这repo热度高,估计是旁边那个phigros-html5项目带起来的?

还是要小心像我一样的yyw(

那有啥的,我也事引诱王,物以类聚呗(不是\ 其实我对yyw没什么概念,或许跟脚本小子差不多?那这种就是修养问题了,到哪里都会招人烦,管也管不住,不如放任自由,无为而治((仅代表个人观点,如有跟我不同的意见,欢迎探讨)

虽然我不觉得yyw有这技术配置这些玩意,所以建议开发的时候留点门槛

可是这个项目我自己也在用,每次操作起来那么多步骤我也嫌烦啊(\ 个人觉得现在这个项目,计时器同步就是一个很高的门槛,而且这个估计后期也优化不掉\ 至于一般的小鬼,第一步装Python 3.10和pip install就卡死了,大可放心(

还有一个比较大的痛点就是scrcpy由于本身是内置录屏的,所以性能消耗特别大,电量蹭蹭蹭往下掉(

如果您之前关注过这个项目,那您应该记得这个项目以前是自带服务端(魔改自scrcpy-server)的。自带的服务端没有内置录屏,无需编码解码,也不会出现0xfffffc0e的错误。 不过后来由于android studio太占地方,以及配置x86、armv7等编译环境太麻烦,就砍掉了(\ 如果确实有省电之类的需求,之后我会考虑把它再加回来

luckylaiCN commented 2 years ago

嗯,自己写服务端可能是有点麻烦。我之前看到过网易开发的airtest下面有一个网易自己开发的Maxtouch(应该是改自minitouch)的兼容性应该比较强,所以就使用了他的jar。可以供作参考。

kvarenzn commented 2 years ago

刚看了一眼minitouch,说是默认不支持Android 10以上,编译还需要ndk。算了还是换回我的scrcpy-server罢(

luckylaiCN commented 2 years ago

maxtouch是minitouch的安卓10以上解决方案,实测可行(

luckylaiCN commented 2 years ago

今天抽空测试了一下,发现OMX.google.h264.encoderc2.android.avc.encoder在本机上是可以正常使用的,不需要更改分辨率。server端传递名是encoder_name

self.server_process = subprocess.Popen( # line 26
            ['adb', 'shell', 'CLASSPATH=/data/local/tmp/scrcpy-server.jar', 'app_process', '/',
             'com.genymobile.scrcpy.Server',
             server_version,
             'log_level=warn',
             'bit_rate=8000000',
             'clipboard_autosync=false',
             'encoder_name=c2.android.avc.encoder'
             ])

example output:

PS D:\project\git\phisap> python .\control.py
scrcpy-server-v1.22: 1 file pushed. 1.3 MB/s (40955 bytes in 0.031s)
tap 0
tap 1
tap 2
tap 3
tap 4
tap 5
tap 6

建议可以在启动时选择encoder,保证兼容性。

luckylaiCN commented 2 years ago

目前可选的encoder有三种:

OMX.hisi.video.encoder.avc
c2.android.avc.encoder
OMX.google.h264.encoder