gstreamer-graphix/api/api.go

167 lines
5.0 KiB
Go

package api
import (
"context"
"fmt"
"git.entr0py.de/garionion/gstreamer-graphix/gstreamer"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
"sync"
"time"
)
type PipelineService struct {
pipelineSlots map[string][]string
pipelineslotmapping map[string]string
UnimplementedPipelineServiceServer
*gstreamer.Gstreamer
Font, FontWeight string //default font
FontSize int // Fontsize 0 does not make sense
Context context.Context
sync.RWMutex
}
func (s *PipelineService) UpdatePipeline(ctx context.Context, updates *PipelineUpdates) (*PipelineUpdateResponse, error) {
pipeline, err := s.Gstreamer.GetPipeline(updates.Id.GetId())
if err != nil {
log.Error().Str("ID", updates.Id.GetId()).Err(err)
} else {
overlays := s.convertRPCOverlayToGstreamerOverlay(updates.GetOverlays())
s.Lock()
pipeline.PipelineUpdates <- gstreamer.PipelineUpdates{Overlays: overlays}
s.Unlock()
}
return &PipelineUpdateResponse{PipelineId: &PipelineID{Id: updates.Id.GetId()}}, nil
}
func (s *PipelineService) StopPipeline(ctx context.Context, id *PipelineID) (*PipelineStopResponse, error) {
pipeline, err := s.Gstreamer.GetPipeline(id.GetId())
if err != nil {
log.Error().Str("ID", id.GetId()).Err(err)
} else {
pipeline.Lock()
err = pipeline.Stop()
pipeline.Unlock()
}
return &PipelineStopResponse{PipelineId: &PipelineID{Id: id.GetId()}}, err
}
func (s *PipelineService) StartPipeline(ctx context.Context, id *PipelineID) (*PipelineStartResponse, error) {
pipeline, err := s.Gstreamer.GetPipeline(id.GetId())
if err != nil {
log.Error().Str("ID", id.GetId()).Err(err)
} else {
pipeline.Lock()
err = pipeline.Start()
pipeline.Unlock()
}
return &PipelineStartResponse{PipelineId: &PipelineID{Id: id.GetId()}}, err
}
func (s *PipelineService) DeletePipeline(ctx context.Context, id *PipelineID) (*PipelineDeleteResponse, error) {
go s.Gstreamer.DeletePipeline(id.GetId())
if slot, ok := s.pipelineslotmapping[id.GetId()]; ok {
s.Lock()
delete(s.pipelineslotmapping, id.GetId())
var i int
for i := range s.pipelineSlots[slot] {
if s.pipelineSlots[slot][i] == id.GetId() {
break
}
}
s.pipelineSlots[slot] = append(s.pipelineSlots[slot][:i], s.pipelineSlots[slot][i+1:]...)
s.Unlock()
}
return &PipelineDeleteResponse{PipelineId: &PipelineID{Id: id.GetId()}}, nil
}
func (s *PipelineService) CreatePipeline(ctx context.Context, pipeline *Pipeline) (*PipelineCreationResponse, error) {
uid, _ := uuid.NewRandom()
id := uid.String()
gstreamerPipeline := &gstreamer.Pipeline{
Name: pipeline.GetName(),
ID: id,
InputElement: gstreamer.InputElement{
Name: fmt.Sprintf("%s-input", pipeline.GetName()),
Type: "filesrc",
Properties: map[string]string{
"location": pipeline.GetClip(),
},
},
OutputElement: gstreamer.OutputElement{
Name: fmt.Sprintf("%s-output", pipeline.GetName()),
Type: pipeline.GetOutput(),
},
}
gstreamerPipeline.Overlays = s.convertRPCOverlayToGstreamerOverlay(pipeline.Overlay)
gstreamerPipeline.Create()
s.Lock()
if _, ok := s.pipelineSlots[pipeline.GetName()]; ok {
s.pipelineSlots[pipeline.GetName()] = append(s.pipelineSlots[pipeline.GetName()], id)
} else {
s.pipelineSlots[pipeline.GetName()] = []string{id}
}
s.pipelineslotmapping[id] = pipeline.GetName()
s.Unlock()
return &PipelineCreationResponse{
PipelineId: &PipelineID{Id: id},
}, nil
}
func (s *PipelineService) convertRPCOverlayToGstreamerOverlay(apiOverlays []*Overlay) map[string]gstreamer.Overlay {
gstreamerOverlays := map[string]gstreamer.Overlay{}
for _, overlay := range apiOverlays {
switch overlay.GetOverlayData().(type) {
case *Overlay_Extra:
log.Error().Msgf("Extra Element not implemented, used by overlay %s", overlay.GetName())
case *Overlay_ImageOverlay:
o := overlay.GetImageOverlay()
imageOverlay := &gstreamer.ImageOverlay{
Name: overlay.GetName(),
Path: o.GetPath(),
X: int(overlay.GetX()),
Y: int(overlay.GetY()),
Display: overlay.GetDisplay(),
BlendIn: time.Duration(overlay.GetBlendIn()),
BlendOut: time.Duration(overlay.GetBlendOut()),
}
gstreamerOverlays[overlay.GetName()] = imageOverlay
case *Overlay_TextOverlay:
o := overlay.GetTextOverlay()
if o.GetText() == "" {
continue
}
font := s.Font
if o.GetFontName() != "" {
font = o.GetFontName()
}
fontsize := s.FontSize
if o.GetFontSize() != 0 {
fontsize = int(o.GetFontSize())
}
fontweight := s.FontWeight
if o.GetFontWeight() != "" {
font = o.GetFontWeight()
}
textOverlay := &gstreamer.TextOverlay{
Name: overlay.GetName(),
X: int(overlay.GetX()),
Y: int(overlay.GetY()),
Font: font,
FontSize: fontsize,
FontWeight: fontweight,
Color: o.GetFontColor(),
Value: o.GetText(),
Display: overlay.GetDisplay(),
MaxWidth: uint(o.GetMaxWidth()),
BlendIn: time.Duration(overlay.GetBlendIn()),
BlendOut: time.Duration(overlay.GetBlendOut()),
}
gstreamerOverlays[overlay.GetName()] = textOverlay
}
}
return gstreamerOverlays
}