Live video on the AT Protocol
at eli/fix-gitlab 71 lines 1.7 kB view raw
1package media 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 "strings" 8 9 "github.com/go-gst/go-gst/gst" 10 "github.com/go-gst/go-gst/gst/app" 11 "stream.place/streamplace/pkg/log" 12) 13 14func Thumbnail(ctx context.Context, r io.Reader, w io.Writer) error { 15 ctx = log.WithLogValues(ctx, "function", "Thumbnail") 16 ctx, cancel := context.WithCancel(ctx) 17 defer cancel() 18 19 pipelineSlice := []string{ 20 "appsrc name=appsrc ! qtdemux name=demux ! decodebin ! videoconvert ! videoscale ! videorate ! capsfilter name=capsfilter caps=video/x-raw,width=[1,1280],height=[1,720],pixel-aspect-ratio=1/1,framerate=1/999999 ! queue ! pngenc snapshot=true ! appsink name=appsink", 21 } 22 23 pipeline, err := gst.NewPipelineFromString(strings.Join(pipelineSlice, "\n")) 24 if err != nil { 25 return fmt.Errorf("error creating Thumbnail pipeline: %w", err) 26 } 27 28 defer func() { 29 cancel() 30 err = pipeline.BlockSetState(gst.StateNull) 31 }() 32 appsrc, err := pipeline.GetElementByName("appsrc") 33 if err != nil { 34 return err 35 } 36 37 src := app.SrcFromElement(appsrc) 38 src.SetCallbacks(&app.SourceCallbacks{ 39 NeedDataFunc: ReaderNeedData(ctx, r), 40 }) 41 42 appsink, err := pipeline.GetElementByName("appsink") 43 if err != nil { 44 return err 45 } 46 47 errCh := make(chan error) 48 go func() { 49 err := HandleBusMessages(ctx, pipeline) 50 cancel() 51 errCh <- err 52 close(errCh) 53 }() 54 55 sink := app.SinkFromElement(appsink) 56 sink.SetCallbacks(&app.SinkCallbacks{ 57 NewSampleFunc: WriterNewSample(ctx, w), 58 }) 59 60 if err := pipeline.BlockSetState(gst.StatePlaying); err != nil { 61 return fmt.Errorf("error setting pipeline state: %w", err) 62 } 63 64 <-ctx.Done() 65 66 if err := pipeline.BlockSetState(gst.StateNull); err != nil { 67 return fmt.Errorf("error setting pipeline state: %w", err) 68 } 69 70 return <-errCh 71}