some fix
This commit is contained in:
parent
b945218c85
commit
708732a37b
@ -47,7 +47,7 @@ func NewConfig() *Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func genconf(c *cli.Context) error {
|
func genconf(c *cli.Context) error {
|
||||||
f, err := os.OpenFile(c.String("config"), os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile(c.String("config"), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// Skip riff header and `fmt ` just 16 bytes
|
// Skip riff header and `fmt ` just 16 bytes
|
||||||
const (
|
const (
|
||||||
FmtHeaderOffset = 0x0c
|
FmtHeaderOffset = 0x0c // 12
|
||||||
FmtHeaderIDSize = 4
|
FmtHeaderIDSize = 4
|
||||||
FmtHeaderChunkSizeSize = 4
|
FmtHeaderChunkSizeSize = 4
|
||||||
FmtHeaderSizeDefault = 16
|
FmtHeaderSizeDefault = 16
|
||||||
@ -49,8 +49,8 @@ func DefaultHeader() *WavHeader {
|
|||||||
|
|
||||||
func (w *WavHeader) Parse(f io.Reader) error {
|
func (w *WavHeader) Parse(f io.Reader) error {
|
||||||
// skip headers
|
// skip headers
|
||||||
var headers [FmtHeaderOffset]byte
|
var _headers [FmtHeaderOffset]byte
|
||||||
if _, err := f.Read(headers[:]); err != nil {
|
if _, err := f.Read(_headers[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ func (w *WavHeader) Parse(f io.Reader) error {
|
|||||||
if _, err := f.Read(id[:]); err != nil {
|
if _, err := f.Read(id[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if bytes.Equal(id[:], []byte{'f', 'm', 't', '0'}[:]) {
|
if bytes.Equal(id[:], []byte("fmt ")) {
|
||||||
return errors.New("bad header")
|
return errors.New("bad header")
|
||||||
}
|
}
|
||||||
w.ID = id
|
w.ID = id
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
package audiodriver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/mediadevices/pkg/io/audio"
|
|
||||||
"github.com/pion/mediadevices/pkg/prop"
|
|
||||||
"github.com/pion/mediadevices/pkg/wave"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
DataChunkIDSize = 4
|
|
||||||
DataChunkSizeSize = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// BufferSize for pcm bytes
|
|
||||||
const BufferSize = 512
|
|
||||||
const BitsPerByte = 8
|
|
||||||
|
|
||||||
type WavFIFODriver struct {
|
|
||||||
PCM <-chan [BufferSize]byte
|
|
||||||
WaveHeader *WavHeader
|
|
||||||
closed <-chan struct{}
|
|
||||||
cancel func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() *WavFIFODriver {
|
|
||||||
return &WavFIFODriver{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavFIFODriver) Open() error {
|
|
||||||
defer logrus.Debug("device opened")
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
w.closed = ctx.Done()
|
|
||||||
w.cancel = cancel
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavFIFODriver) Close() error {
|
|
||||||
w.cancel()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavFIFODriver) Properties() []prop.Media {
|
|
||||||
logrus.Debugf("wave header: %v", w.WaveHeader)
|
|
||||||
return []prop.Media{
|
|
||||||
{
|
|
||||||
Audio: prop.Audio{
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavFIFODriver) AudioRecord(p prop.Media) (audio.Reader, error) {
|
|
||||||
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
|
|
||||||
case pcmData, ok := <-w.PCM:
|
|
||||||
logrus.Debug("got %d bytes pcm data", len(pcmData))
|
|
||||||
if !ok {
|
|
||||||
return nil, func() {}, io.ErrClosedPipe
|
|
||||||
}
|
|
||||||
copy(a.Data, bytesTo16BitSamples(pcmData[:]))
|
|
||||||
case <-time.After(p.Latency):
|
|
||||||
}
|
|
||||||
return a, func() {}, nil
|
|
||||||
}
|
|
||||||
return audio.ReaderFunc(reader), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytesTo16BitSamples(b []byte) []int16 {
|
|
||||||
samples := make([]int16, 0)
|
|
||||||
for i := 0; i < len(b); i += 2 {
|
|
||||||
sample := binary.LittleEndian.Uint16(b[i : i+1])
|
|
||||||
samples = append(samples, int16(sample))
|
|
||||||
}
|
|
||||||
return samples
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package audiodriver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Skip riff header and `fmt ` just 16 bytes
|
|
||||||
const (
|
|
||||||
FmtHeaderOffset = 0x0c
|
|
||||||
FmtHeaderIDSize = 4
|
|
||||||
FmtHeaderChunkSizeSize = 4
|
|
||||||
FmtHeaderSizeDefault = 16
|
|
||||||
)
|
|
||||||
|
|
||||||
type WavHeader struct {
|
|
||||||
ID [4]byte
|
|
||||||
Size uint32
|
|
||||||
AudioFormat uint16
|
|
||||||
NumChannels uint16
|
|
||||||
SampleRate uint32
|
|
||||||
ByteRate uint32
|
|
||||||
BlockAlign uint16
|
|
||||||
BitsPerSample uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHeader(f io.Reader) (*WavHeader, error) {
|
|
||||||
w := &WavHeader{}
|
|
||||||
if err := w.Parse(f); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return w, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DefaultHeader() *WavHeader {
|
|
||||||
return &WavHeader{
|
|
||||||
Size: uint32(FmtHeaderSizeDefault),
|
|
||||||
AudioFormat: 1,
|
|
||||||
NumChannels: 2,
|
|
||||||
SampleRate: 48000, // opus only support 48kHz
|
|
||||||
BlockAlign: 4,
|
|
||||||
BitsPerSample: 16,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavHeader) Parse(f io.Reader) error {
|
|
||||||
// skip headers
|
|
||||||
var headers [FmtHeaderOffset]byte
|
|
||||||
if _, err := f.Read(headers[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var id [4]byte
|
|
||||||
if _, err := f.Read(id[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if bytes.Equal(id[:], []byte{'f', 'm', 't', '0'}[:]) {
|
|
||||||
return errors.New("bad header")
|
|
||||||
}
|
|
||||||
w.ID = id
|
|
||||||
|
|
||||||
var size [4]byte
|
|
||||||
if _, err := f.Read(size[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.Size = binary.LittleEndian.Uint32(size[:])
|
|
||||||
|
|
||||||
var af [2]byte
|
|
||||||
if _, err := f.Read(af[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.AudioFormat = binary.LittleEndian.Uint16(af[:])
|
|
||||||
|
|
||||||
var nc [2]byte
|
|
||||||
if _, err := f.Read(nc[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.NumChannels = binary.LittleEndian.Uint16(nc[:])
|
|
||||||
|
|
||||||
var sr [4]byte
|
|
||||||
if _, err := f.Read(sr[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.SampleRate = binary.LittleEndian.Uint32(sr[:])
|
|
||||||
|
|
||||||
var br [4]byte
|
|
||||||
if _, err := f.Read(br[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.ByteRate = binary.LittleEndian.Uint32(br[:])
|
|
||||||
|
|
||||||
var ba [2]byte
|
|
||||||
if _, err := f.Read(ba[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.BlockAlign = binary.LittleEndian.Uint16(ba[:])
|
|
||||||
|
|
||||||
var bps [2]byte
|
|
||||||
if _, err := f.Read(bps[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.BitsPerSample = binary.LittleEndian.Uint16(bps[:])
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavHeader) String() string {
|
|
||||||
b, _ := json.Marshal(w)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WavHeader) GetLatnecy() time.Duration {
|
|
||||||
return time.Millisecond * time.Duration(BufferSize) / time.Duration(w.SampleRate) / time.Duration(w.NumChannels)
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/pion/mediadevices/pkg/codec/opus"
|
"github.com/pion/mediadevices/pkg/codec/opus"
|
||||||
"github.com/pion/mediadevices/pkg/codec/x264"
|
"github.com/pion/mediadevices/pkg/codec/x264"
|
||||||
"github.com/pion/mediadevices/pkg/driver"
|
"github.com/pion/mediadevices/pkg/driver"
|
||||||
"github.com/pion/mediadevices/pkg/prop"
|
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -24,7 +23,7 @@ func New(o *Options) (*Connection, error) {
|
|||||||
connection := &Connection{
|
connection := &Connection{
|
||||||
option: o,
|
option: o,
|
||||||
}
|
}
|
||||||
codecSelector, err := setupCodec(o.Video.BPS)
|
codecSelector, err := setupCodec(o.VideoBPS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -45,10 +44,7 @@ func New(o *Options) (*Connection, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
|
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) {},
|
Audio: func(mtc *mediadevices.MediaTrackConstraints) {},
|
||||||
Codec: codecSelector,
|
Codec: codecSelector,
|
||||||
})
|
})
|
||||||
|
@ -2,11 +2,7 @@ package webrtcconnection
|
|||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
STUNServers []string `yaml:"stun_servers"`
|
STUNServers []string `yaml:"stun_servers"`
|
||||||
Video struct {
|
VideoBPS int `yaml:"video_bps"`
|
||||||
Height int `yaml:"height"`
|
|
||||||
Width int `yaml:"width"`
|
|
||||||
BPS int `yaml:"bps"`
|
|
||||||
} `yaml:"video"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleOptions() *Options {
|
func ExampleOptions() *Options {
|
||||||
@ -15,9 +11,7 @@ func ExampleOptions() *Options {
|
|||||||
"stun:stun.l.google.com:19302",
|
"stun:stun.l.google.com:19302",
|
||||||
"stun:wetofu.me:3478",
|
"stun:wetofu.me:3478",
|
||||||
},
|
},
|
||||||
|
VideoBPS: 500_000,
|
||||||
}
|
}
|
||||||
options.Video.BPS = 500_000
|
|
||||||
options.Video.Height = 768
|
|
||||||
options.Video.Width = 1024
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,58 @@
|
|||||||
package qemuserver
|
package qemuserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
QmpAddress string `yaml:"address"`
|
QmpAddress string `yaml:"address"`
|
||||||
Timeout time.Duration `yaml:"timeout"`
|
Timeout time.Duration `yaml:"timeout"`
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
VNCAddress string `yaml:"vnc"`
|
Audio AudioOptions `yaml:"audio_options"`
|
||||||
AudioPipe string `yaml:"audio_pipe"`
|
Video VideoOptions `yaml:"video_options"`
|
||||||
AudioDevice string `yaml:"audio_device"`
|
}
|
||||||
|
|
||||||
|
type AudioOptions struct {
|
||||||
|
Device string `yaml:"device"`
|
||||||
|
BufferSize uint16 `yaml:"buffer_size"` // in bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
type VideoOptions struct {
|
||||||
|
Height int `yaml:"height"`
|
||||||
|
Width int `yaml:"width"`
|
||||||
|
FPS float32 `yaml:"fps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleOptions() *Options {
|
func ExampleOptions() *Options {
|
||||||
return &Options{
|
return &Options{
|
||||||
QmpAddress: (&url.URL{
|
QmpAddress: (&url.URL{
|
||||||
Scheme: "unix",
|
Scheme: "tcp",
|
||||||
Path: "/tmp/qemu.sock",
|
Host: "localhost:4444",
|
||||||
}).String(),
|
}).String(),
|
||||||
Timeout: time.Duration(60 * time.Second),
|
Timeout: time.Duration(30 * time.Second),
|
||||||
Name: "ace-qemu",
|
Name: "ace-qemu",
|
||||||
VNCAddress: "localhost:5900",
|
Audio: AudioOptions{
|
||||||
AudioPipe: "/tmp/audio",
|
Device: "snd0",
|
||||||
AudioDevice: "snd0",
|
BufferSize: 2048,
|
||||||
|
},
|
||||||
|
Video: VideoOptions{
|
||||||
|
Height: 1024,
|
||||||
|
Width: 768,
|
||||||
|
FPS: 60,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Options) MakeFIFO() error {
|
func (o *Options) MakeFIFO() (string, error) {
|
||||||
os.Remove(o.AudioPipe)
|
path := path.Join(
|
||||||
return syscall.Mkfifo(o.AudioPipe, 0600)
|
os.TempDir(),
|
||||||
|
fmt.Sprintf("%s-%s-audio", o.Name, o.Audio.Device),
|
||||||
|
)
|
||||||
|
os.Remove(path)
|
||||||
|
return path, syscall.Mkfifo(path, 0600)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"git.sense-t.eu.org/ACE/ace/drivers/audio"
|
"git.sense-t.eu.org/ACE/ace/drivers/audio"
|
||||||
"git.sense-t.eu.org/ACE/ace/drivers/video"
|
"git.sense-t.eu.org/ACE/ace/drivers/video"
|
||||||
"git.sense-t.eu.org/ACE/ace/lib/audiodriver"
|
|
||||||
"git.sense-t.eu.org/ACE/ace/lib/qemuconnection"
|
"git.sense-t.eu.org/ACE/ace/lib/qemuconnection"
|
||||||
"github.com/digitalocean/go-qemu/qemu"
|
"github.com/digitalocean/go-qemu/qemu"
|
||||||
"github.com/digitalocean/go-qemu/qmp"
|
"github.com/digitalocean/go-qemu/qmp"
|
||||||
@ -36,15 +35,11 @@ type Server struct {
|
|||||||
var DefaultServer *Server
|
var DefaultServer *Server
|
||||||
|
|
||||||
func NewServer(o *Options) (*Server, error) {
|
func NewServer(o *Options) (*Server, error) {
|
||||||
if err := o.MakeFIFO(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
server := &Server{
|
server := &Server{
|
||||||
options: o,
|
options: o,
|
||||||
audioHeader: make(chan *audio.WavHeader, 1),
|
audioHeader: make(chan *audio.WavHeader, 1),
|
||||||
pcm: make(chan []byte),
|
pcm: make(chan []byte),
|
||||||
ppm: make(chan io.ReadCloser),
|
ppm: make(chan io.ReadCloser, 60), // to be configured
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(o.QmpAddress)
|
u, err := url.Parse(o.QmpAddress)
|
||||||
@ -77,7 +72,7 @@ func NewServer(o *Options) (*Server, error) {
|
|||||||
audio := &audio.PCMStreamDriver{
|
audio := &audio.PCMStreamDriver{
|
||||||
PCM: server.pcm,
|
PCM: server.pcm,
|
||||||
WaveHeader: waveHeader,
|
WaveHeader: waveHeader,
|
||||||
BufferSizeByBytes: 2048, // to be configured
|
BufferSizeByBytes: o.Audio.BufferSize, // to be configured
|
||||||
}
|
}
|
||||||
if err := driver.GetManager().Register(
|
if err := driver.GetManager().Register(
|
||||||
audio,
|
audio,
|
||||||
@ -91,9 +86,9 @@ func NewServer(o *Options) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
video := &video.PPMStreamDriver{
|
video := &video.PPMStreamDriver{
|
||||||
Height: 768,
|
Height: o.Video.Height,
|
||||||
Width: 1024,
|
Width: o.Video.Width,
|
||||||
FPS: 60,
|
FPS: o.Video.FPS,
|
||||||
PPMImage: server.ppm,
|
PPMImage: server.ppm,
|
||||||
}
|
}
|
||||||
if err := driver.GetManager().Register(
|
if err := driver.GetManager().Register(
|
||||||
@ -112,9 +107,26 @@ func NewServer(o *Options) (*Server, error) {
|
|||||||
|
|
||||||
func (s *Server) Run() error {
|
func (s *Server) Run() error {
|
||||||
logrus.Debug("qemu server running")
|
logrus.Debug("qemu server running")
|
||||||
|
path, err := s.options.MakeFIFO()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
f, err := os.Open(s.options.AudioPipe)
|
logrus.Debug("screen capture start")
|
||||||
|
defer close(s.ppm)
|
||||||
|
for range time.Tick(time.Second / time.Duration(s.options.Video.FPS)) { // to be configured
|
||||||
|
ppm, err := s.qemu.ScreenDump()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.ppm <- ppm
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -123,9 +135,9 @@ func (s *Server) Run() error {
|
|||||||
|
|
||||||
logrus.Debug("skip wave headers, to the PCM!")
|
logrus.Debug("skip wave headers, to the PCM!")
|
||||||
// skip to pcm data, for 44 bytes.
|
// skip to pcm data, for 44 bytes.
|
||||||
var _dataChunkHeader [audiodriver.FmtHeaderOffset +
|
var _dataChunkHeader [audio.FmtHeaderOffset +
|
||||||
audiodriver.FmtHeaderIDSize + audiodriver.FmtHeaderChunkSizeSize + waveHeaderSize +
|
audio.FmtHeaderIDSize + audio.FmtHeaderChunkSizeSize + waveHeaderSize +
|
||||||
audiodriver.DataChunkIDSize + audiodriver.DataChunkSizeSize]byte
|
audio.DataChunkIDSize + audio.DataChunkSizeSize]byte
|
||||||
if _, err := f.Read(_dataChunkHeader[:]); err != nil {
|
if _, err := f.Read(_dataChunkHeader[:]); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -139,7 +151,7 @@ func (s *Server) Run() error {
|
|||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case s.pcm <- b:
|
case s.pcm <- b:
|
||||||
case <-time.After(waveHeader.GetLatnecy(2048)):
|
case <-time.After(waveHeader.GetLatnecy(s.options.Audio.BufferSize)):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -151,8 +163,8 @@ func (s *Server) Run() error {
|
|||||||
Args: map[string]string{
|
Args: map[string]string{
|
||||||
"command-line": fmt.Sprintf(
|
"command-line": fmt.Sprintf(
|
||||||
"wavcapture %s %s %d %d %d",
|
"wavcapture %s %s %d %d %d",
|
||||||
s.options.AudioPipe,
|
path,
|
||||||
s.options.AudioDevice,
|
s.options.Audio.Device,
|
||||||
waveHeader.SampleRate,
|
waveHeader.SampleRate,
|
||||||
waveHeader.BitsPerSample,
|
waveHeader.BitsPerSample,
|
||||||
waveHeader.NumChannels,
|
waveHeader.NumChannels,
|
||||||
@ -164,19 +176,6 @@ func (s *Server) Run() error {
|
|||||||
logrus.Debug("audio capture set")
|
logrus.Debug("audio capture set")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
|
||||||
logrus.Debug("screen capture start")
|
|
||||||
defer close(s.ppm)
|
|
||||||
for range time.Tick(time.Second / 60) { // to be configured
|
|
||||||
ppm, err := s.qemu.ScreenDump()
|
|
||||||
if err != nil {
|
|
||||||
logrus.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s.ppm <- ppm
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user