diff --git a/cmd/server/server.go b/cmd/server/server.go
index 483ce4a..a81b702 100644
--- a/cmd/server/server.go
+++ b/cmd/server/server.go
@@ -54,6 +54,7 @@ func (s *Server) Run() error {
logrus.Fatal("cannot run qemuserver with error: ", err)
}
}()
+ logrus.Debug("qemu server running")
return webServer.Run()
}
diff --git a/lib/audiodriver/wavfifo.go b/lib/audiodriver/wavfifo.go
index 85adb76..0d16517 100644
--- a/lib/audiodriver/wavfifo.go
+++ b/lib/audiodriver/wavfifo.go
@@ -23,7 +23,7 @@ const BitsPerByte = 8
type WavFIFODriver struct {
PCM <-chan [BufferSize]byte
- WaveHeader <-chan *WavHeader
+ WaveHeader *WavHeader
closed <-chan struct{}
cancel func()
}
@@ -42,19 +42,19 @@ func (w *WavFIFODriver) Open() error {
}
func (w *WavFIFODriver) Close() error {
- defer w.cancel()
+ w.cancel()
return nil
}
func (w *WavFIFODriver) Properties() []prop.Media {
- waveHeader := <-w.WaveHeader
- logrus.Debugf("wave header: %v", waveHeader)
+ logrus.Debugf("wave header: %v", w.WaveHeader)
return []prop.Media{
{
Audio: prop.Audio{
- SampleRate: int(waveHeader.SampleRate),
- ChannelCount: int(waveHeader.NumChannels),
- Latency: waveHeader.GetLatnecy(),
+ SampleRate: int(w.WaveHeader.SampleRate),
+ ChannelCount: int(w.WaveHeader.NumChannels),
+ SampleSize: int(w.WaveHeader.BitsPerSample),
+ Latency: w.WaveHeader.GetLatnecy(),
IsFloat: false, // just 8bit or 16bit with qemu
IsBigEndian: false, // qemu should be little endian
IsInterleaved: true,
@@ -64,13 +64,14 @@ func (w *WavFIFODriver) Properties() []prop.Media {
}
func (w *WavFIFODriver) AudioRecord(p prop.Media) (audio.Reader, error) {
- a := wave.NewInt16Interleaved(wave.ChunkInfo{
- Len: BufferSize / int(p.SampleSize/BitsPerByte),
- Channels: p.ChannelCount,
- SamplingRate: p.SampleRate,
- })
+ logrus.Debug(p)
reader := func() (wave.Audio, func(), error) {
+ a := wave.NewInt16Interleaved(wave.ChunkInfo{
+ Len: BufferSize / int(p.SampleSize/BitsPerByte),
+ Channels: p.ChannelCount,
+ SamplingRate: p.SampleRate,
+ })
select {
case <-w.closed:
return nil, func() {}, io.EOF
diff --git a/lib/qemuconnection/events.go b/lib/qemuconnection/events.go
index 3ece627..e03cbd7 100644
--- a/lib/qemuconnection/events.go
+++ b/lib/qemuconnection/events.go
@@ -29,7 +29,7 @@ type CommandLine struct {
}
func ParseEvent(b []byte) (*Event, error) {
- var event *Event
+ event := &Event{}
if err := json.Unmarshal(b, event); err != nil {
return nil, err
}
diff --git a/lib/webrtcconnection/connection.go b/lib/webrtcconnection/connection.go
index 19a3adb..d827d8c 100644
--- a/lib/webrtcconnection/connection.go
+++ b/lib/webrtcconnection/connection.go
@@ -6,6 +6,7 @@ import (
"github.com/pion/mediadevices/pkg/codec/opus"
"github.com/pion/mediadevices/pkg/codec/x264"
"github.com/pion/mediadevices/pkg/driver"
+ "github.com/pion/mediadevices/pkg/prop"
"github.com/pion/webrtc/v3"
"github.com/sirupsen/logrus"
)
@@ -45,7 +46,10 @@ func New(o *Options) (*Connection, error) {
}
s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
- Video: func(mtc *mediadevices.MediaTrackConstraints) {},
+ Video: func(mtc *mediadevices.MediaTrackConstraints) {
+ mtc.Height = prop.Int(o.Video.Height)
+ mtc.Width = prop.Int(o.Video.Width)
+ },
Audio: func(mtc *mediadevices.MediaTrackConstraints) {},
Codec: codecSelector,
})
@@ -84,7 +88,7 @@ func (c *Connection) Regist(offer *webrtc.SessionDescription) (*webrtc.SessionDe
for _, track := range c.stream.GetTracks() {
track.OnEnded(func(err error) {
- logrus.Errorf("Track (ID: %s) ended with error: %v", track.ID(), err)
+ logrus.Errorf("Track (ID: %s, kind: %s) ended with error: %v", track.ID(), track.Kind().String(), err)
})
_, err := rtc.AddTransceiverFromTrack(track, webrtc.RTPTransceiverInit{
Direction: webrtc.RTPTransceiverDirectionSendonly,
diff --git a/servers/qemuserver/server.go b/servers/qemuserver/server.go
index f5f0bf8..a4ae5f3 100644
--- a/servers/qemuserver/server.go
+++ b/servers/qemuserver/server.go
@@ -15,12 +15,19 @@ import (
"github.com/sirupsen/logrus"
)
+const waveHeaderSize = 16
+
+var waveHeader = &audiodriver.WavHeader{
+ Size: waveHeaderSize,
+ AudioFormat: 1,
+ NumChannels: 2,
+ SampleRate: 44100,
+ BlockAlign: 4,
+ BitsPerSample: 16,
+}
+
type Server struct {
- options *Options
- QmpConnector struct {
- RX chan *qemuconnection.Event
- TX chan qemu.Status
- }
+ options *Options
qemu *qemu.Domain
audioHeader chan *audiodriver.WavHeader
pcm chan [audiodriver.BufferSize]byte
@@ -38,8 +45,6 @@ func NewServer(o *Options) (*Server, error) {
audioHeader: make(chan *audiodriver.WavHeader, 1),
pcm: make(chan [audiodriver.BufferSize]byte),
}
- server.QmpConnector.RX = make(chan *qemuconnection.Event)
- server.QmpConnector.TX = make(chan qemu.Status)
u, err := url.Parse(o.QmpAddress)
if err != nil {
@@ -80,7 +85,7 @@ func NewServer(o *Options) (*Server, error) {
return nil, err
}
audio.PCM = server.pcm
- audio.WaveHeader = server.audioHeader
+ audio.WaveHeader = waveHeader
if err := driver.GetManager().Register(
vncdriver.NewVnc(o.VNCAddress),
@@ -98,84 +103,26 @@ func NewServer(o *Options) (*Server, error) {
func (s *Server) Run() error {
logrus.Debug("qemu server running")
- defer logrus.Debug("qemu server exit")
- defer s.qemu.Close()
- s.startCapture()
- logrus.Debug("qemu capture start")
-
- for ev := range s.QmpConnector.RX {
- if ev.Type == qemuconnection.QueryStatusEvent {
- status, err := s.qemu.Status()
- if err != nil {
- logrus.Error("get qemu status error: ", err)
- continue
- }
- s.QmpConnector.TX <- status
- continue
- }
- for _, cmd := range ev.ToQemuCommand() {
- _, err := s.qemu.Run(cmd)
- if err != nil {
- logrus.Error("run command error: ", err)
- }
- }
- }
- return nil
-}
-
-func (s *Server) startCapture() {
- const waveHeaderSize = 16
- waveHeader := &audiodriver.WavHeader{
- Size: waveHeaderSize,
- AudioFormat: 1,
- NumChannels: 2,
- SampleRate: 44100,
- BlockAlign: 4,
- BitsPerSample: 16,
+ f, err := os.Open(s.options.AudioPipe)
+ if err != nil {
+ logrus.Fatal(err)
}
+ defer f.Close()
+ logrus.Debug("start reading fifo")
go func() {
- f, err := os.Open(s.options.AudioPipe)
- if err != nil {
- logrus.Fatal(err)
- }
- defer f.Close()
-
- logrus.Debug("start reading from fifo")
-
- s.audioHeader <- waveHeader
- close(s.audioHeader) // only once
-
- // skip to pcm data, for 44 bytes.
- var _dataChunkHeader [audiodriver.FmtHeaderOffset +
- audiodriver.FmtHeaderIDSize + audiodriver.FmtHeaderChunkSizeSize + waveHeaderSize +
- audiodriver.DataChunkIDSize + audiodriver.DataChunkSizeSize]byte
- if _, err := f.Read(_dataChunkHeader[:]); err != nil {
- logrus.Fatal(err)
- }
-
- defer close(s.pcm)
- for {
- var b [audiodriver.BufferSize]byte
- if _, err := f.Read(b[:]); err != nil {
- logrus.Error(err)
- }
- select {
- case s.pcm <- b:
- case <-time.After(waveHeader.GetLatnecy()):
- }
- }
- }()
-
- go func() {
+ logrus.Debug("setting audio capture")
if _, err := s.qemu.Run(qmp.Command{
Execute: "human-monitor-command",
Args: map[string]string{
"command-line": fmt.Sprintf(
- "wavcapture %s %s",
+ "wavcapture %s %s %d %d %d",
s.options.AudioPipe,
s.options.AudioDevice,
+ waveHeader.SampleRate,
+ waveHeader.BitsPerSample,
+ waveHeader.NumChannels,
),
},
}); err != nil {
@@ -183,6 +130,27 @@ func (s *Server) startCapture() {
}
logrus.Debug("audio capture set")
}()
+
+ logrus.Debug("skip wave headers, to the PCM!")
+ // skip to pcm data, for 44 bytes.
+ var _dataChunkHeader [audiodriver.FmtHeaderOffset +
+ audiodriver.FmtHeaderIDSize + audiodriver.FmtHeaderChunkSizeSize + waveHeaderSize +
+ audiodriver.DataChunkIDSize + audiodriver.DataChunkSizeSize]byte
+ if _, err := f.Read(_dataChunkHeader[:]); err != nil {
+ logrus.Fatal(err)
+ }
+
+ defer close(s.pcm)
+ for {
+ var b [audiodriver.BufferSize]byte
+ if _, err := f.Read(b[:]); err != nil {
+ logrus.Error(err)
+ }
+ select {
+ case s.pcm <- b:
+ case <-time.After(waveHeader.GetLatnecy()):
+ }
+ }
}
func (s *Server) SendEvent(b []byte) error {
@@ -190,13 +158,19 @@ func (s *Server) SendEvent(b []byte) error {
if err != nil {
return err
}
- s.QmpConnector.RX <- ev
+ for _, cmd := range ev.ToQemuCommand() {
+ _, err := s.qemu.Run(cmd)
+ if err != nil {
+ return err
+ }
+ }
return nil
}
func (s *Server) GetStatus() qemu.Status {
- s.QmpConnector.RX <- &qemuconnection.Event{
- Type: qemuconnection.QueryStatusEvent,
+ status, err := s.qemu.Status()
+ if err != nil {
+ return qemu.StatusIOError
}
- return <-s.QmpConnector.TX
+ return status
}
diff --git a/web/src/components/AceScreen.vue b/web/src/components/AceScreen.vue
index 201a3e2..4645b60 100644
--- a/web/src/components/AceScreen.vue
+++ b/web/src/components/AceScreen.vue
@@ -1,5 +1,8 @@
-
+