Ready-to-use SRT / WebRTC / RTSP / RTMP / LL-HLS media server and media proxy that allows to read, publish, proxy, record and playback video and audio streams.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

134 lines
2.3 KiB

//go:build rpicamera
// +build rpicamera
package rpicamera
import (
_ "embed"
"fmt"
"strconv"
"github.com/aler9/gortsplib/pkg/h264"
)
//go:embed exe/exe
var exeContent []byte
type RPICamera struct {
onData func([][]byte)
exe *embeddedExe
pipe *pipe
waitDone chan error
readerDone chan error
}
func New(
params Params,
onData func([][]byte),
) (*RPICamera, error) {
pipe, err := newPipe()
if err != nil {
return nil, err
}
env := []string{
"PIPE_FD=" + strconv.FormatInt(int64(pipe.writeFD), 10),
"CAMERA_ID=" + strconv.FormatInt(int64(params.CameraID), 10),
"WIDTH=" + strconv.FormatInt(int64(params.Width), 10),
"HEIGHT=" + strconv.FormatInt(int64(params.Height), 10),
"FPS=" + strconv.FormatInt(int64(params.FPS), 10),
"IDR_PERIOD=" + strconv.FormatInt(int64(params.IDRPeriod), 10),
"BITRATE=" + strconv.FormatInt(int64(params.Bitrate), 10),
"PROFILE=" + params.Profile,
"LEVEL=" + params.Level,
}
exe, err := newEmbeddedExe(exeContent, env)
if err != nil {
pipe.close()
return nil, err
}
waitDone := make(chan error)
go func() {
waitDone <- exe.cmd.Wait()
}()
readerDone := make(chan error)
go func() {
readerDone <- func() error {
buf, err := pipe.read()
if err != nil {
return err
}
switch buf[0] {
case 'e':
return fmt.Errorf(string(buf[1:]))
case 'r':
return nil
default:
return fmt.Errorf("unexpected output from pipe (%c)", buf[0])
}
}()
}()
select {
case <-waitDone:
exe.close()
pipe.close()
<-readerDone
return nil, fmt.Errorf("process exited unexpectedly")
case err := <-readerDone:
if err != nil {
exe.close()
<-waitDone
pipe.close()
return nil, err
}
}
readerDone = make(chan error)
go func() {
readerDone <- func() error {
for {
buf, err := pipe.read()
if err != nil {
return err
}
if buf[0] != 'b' {
return fmt.Errorf("unexpected output from pipe (%c)", buf[0])
}
buf = buf[1:]
nalus, err := h264.AnnexBUnmarshal(buf)
if err != nil {
return err
}
onData(nalus)
}
}()
}()
return &RPICamera{
onData: onData,
exe: exe,
pipe: pipe,
waitDone: waitDone,
readerDone: readerDone,
}, nil
}
func (c *RPICamera) Close() {
c.exe.close()
<-c.waitDone
c.pipe.close()
<-c.readerDone
}