首先我不会Linux ,只会Win系统,我不会C#、C++和JAVA,我会些GOLANG基础和易语言
看scrcpy-server和ffmpeg的源码根本看不懂,所以遇到难度,求爱心人帮解决。
我的对于scrcpy-server的步骤如下:
1、上传到手机:adb push scrcpy-server /data/local/tmp/scrcpy-server.jar
2、提升权限:adb shell chmod 0755 /data/local/tmp/scrcpy-server.jar
3、添加映射:adb forward tcp:3031 localabstract:scrcpy
4、启动应用服务:adb shell CLASSPATH=/data/local/tmp/AuxControl.jar app_process / com.genymobile.scrcpy.Server 1.24 tunnel_forward=true control=false
5、自己用golang编写TCP客户端,连接3031端口,收到实时视频流数据,但是一直没有办法解决沾包问题。
通过外网寻找scrcpy-server 相关资料,得到的是(手机服务端在发送一帧数据包前,会先发送pts 信息,和包长度,所以在客户端进行解码这部分的视频流的时候,先取出12个字节,其中8个字节是long类型,为pts时间戳,4个字节是数据包长度,意味着这一帧的长度,只有将这个长度的内容完整读取,才能正常渲染,如果某一次因为缓冲没有读取完,那只有等待下次继续读取,直到读取到数据的尾部。最后送显),括号的解释看似简单,我采用GO和易语言读取12个字节,在读取后4个字节,一直得不到数据流的真实数据长度。
对于ffmpeg,看不懂源码,更不知道怎么调用DLL来实现。
如果你能解决的问题,参考以下任何一种方式来解决:
1、对于JAVA,直接修改scrcpy-server源码实现,发送完整包,不要分包发送。也可以改为Web Socket方式转发出来,不需要转码,只要完整的H264
2、对于C语言,写成DLL,动态创建Web Socket把数据转发出来
3、关于ws-scrcpy,我是一直没有安装成功过包括WIN和LInux,但是有个docker版本,安装成功了,但是不能控制,对与ws-scrcpy也是不熟悉,NODEJS代码还好,里面又包含了其他的一种语言,至于怎么接收屏幕数据到显示,在到控制等消息格式,更是不清楚。
你遇到的问题挺有难度的,我可以给你提供一些思路和建议。
针对你在使用GO语言读取12个字节的情况,你可以考虑使用binary.Read()函数,以确保正确地获取相应的数据类型。像这样:
import (
"bytes"
"encoding/binary"
)
bytesReader := bytes.NewReader(buffer) // buffer是读取到的数据包
var pts int64
var length int32
err := binary.Read(bytesReader, binary.LittleEndian, &pts)
if err != nil {
panic(err)
}
err = binary.Read(bytesReader, binary.LittleEndian, &length)
if err != nil {
panic(err)
}
这段代码会自动地将字节流解析成对应的数据类型。
关于FFmpeg的使用,你可以考虑在GO语言中使用FFmpeg的API或库文件来解决你的问题。你可以使用ffmpeg的API调用,对H264流进行解码,获取每一帧的图像数据。其中,FFmpeg提供了一些已经实现好的解码器,如h264解码器。你需要读取H264流,将读取到的数据通过解码器进行解码,获取每一帧图像的数据。
此外,如果你打算使用C语言来实现,你可以将FFmpeg封装成DLL库文件,使用C语言中动态链接库的相关函数,将FFmpeg集成到你的代码中。
针对你提到的ws-scrcpy,它是一种基于Websocket协议的Android设备屏幕共享工具,它可以使用JavaScript或Node.js实现。其中,前端可以通过WebSocket协议获取H264码流并将其展示出来,后端则可以使用FFmpeg进行视频解码,以获取每一帧的图像数据。如果你感兴趣,你可以了解一下WebSocket和Node.js相关的知识,这可能会对你的开发有所帮助。
我看你用的好像是开源的那个 scrcpy,你是要修改它的源码实现什么别的效果么?我本地用官方给的绿色版客户端是可以运行的,不过最新的版本也是无法链接,不知道是手机系统的原因还是咋回事。
目前我是用的1.20版本,是可以正常投屏操控的。
该回答引用ChatGPT
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"net"
)
const (
headerLen = 12 // 头部长度
)
func main() {
conn, err := net.Dial("tcp", "localhost:3031")
if err != nil {
fmt.Println("dial error:", err)
return
}
defer conn.Close()
buf := make([]byte, 1024*1024*10) // 缓冲区大小可以根据实际情况调整
var (
pts int64 // 时间戳
frameLen uint32 // 数据包长度
readLen int // 已读取数据长度
remainLen int // 剩余数据长度
lastOffset int // 上一帧数据的结束位置
)
for {
headBuf := make([]byte, headerLen)
_, err := io.ReadFull(conn, headBuf)
if err != nil {
fmt.Println("read header error:", err)
return
}
r := bytes.NewReader(headBuf[:8])
binary.Read(r, binary.LittleEndian, &pts) // 解析时间戳
r = bytes.NewReader(headBuf[8:])
binary.Read(r, binary.LittleEndian, &frameLen) // 解析数据包长度
remainLen = int(frameLen) // 设置剩余数据长度
for remainLen > 0 {
readLen, err = conn.Read(buf[lastOffset+int(frameLen)-remainLen : lastOffset+int(frameLen)])
if err != nil {
fmt.Println("read body error:", err)
return
}
remainLen -= readLen // 更新剩余数据长度
}
lastOffset += int(frameLen) // 更新上一帧数据的结束位置
if lastOffset+int(frameLen) > len(buf) { // 缓冲区已满,清空
lastOffset = 0
}
// 在这里进行数据的解码和展示
}
}
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
对于您的问题,我会尝试给出一些解决方案:
修改scrcpy-server源码实现完整数据包的发送:
您可以尝试在scrcpy-server源码的send_frame函数中,将H264的帧数据直接打包成完整的数据包,发送给TCP客户端。具体的方法是在send_frame函数中,将分包发送的逻辑删除,并将pts信息和包长度的信息打包成完整的数据包一同发送出去。
编写C语言的DLL,动态创建Web Socket来转发数据:
您可以尝试使用C++和websocketpp库来编写动态链接库,动态创建Web Socket将数据转发出去。具体的方法是通过websocketpp库实现Web Socket服务器端的创建,然后在DLL中调用websocketpp库,将H264的帧数据发送给Web Socket服务器端。客户端通过连接Web Socket服务器端来接收数据。
尝试使用ws-scrcpy:
ws-scrcpy是一个基于Web Socket的Android远程控制方案,可以实现屏幕数据的传输和控制。您可以尝试按照官方文档一步步安装和配置ws-scrcpy,并使用相应的代码来使屏幕数据传输到客户端。如果在使用过程中有问题,可以尝试查看相关文档和代码,或者咨询官方支持。
如果我的回答解决了您的问题,请采纳!