Skip to content

Instantly share code, notes, and snippets.

@bradfitz
Created September 3, 2011 06:25
Show Gist options
  • Save bradfitz/1190721 to your computer and use it in GitHub Desktop.
Save bradfitz/1190721 to your computer and use it in GitHub Desktop.
go x11 mpeg stream viewer
// X11 viewer for a MJPEG stream, such as the one obtained from the
// Android app https://market.android.com/details?id=com.pas.webcam
package main
import (
"exp/gui/x11"
"flag"
"http"
"image"
"image/draw"
"image/jpeg"
"log"
"mime"
"mime/multipart"
"strings"
)
var (
stream = flag.String("stream", "http://10.0.0.212:8080/videofeed", "MJPEG stream")
flush = flag.Bool("flush", true, "flush x11 after each frame")
)
func main() {
flag.Parse()
res, err := http.Get(*stream)
if err != nil {
log.Fatalf("GET of %q: %v", *stream, err)
}
log.Printf("Content: %v", res.Header.Get("Content-Type"))
_, params, err := mime.ParseMediaType(res.Header.Get("Content-Type"))
if err != nil {
log.Fatalf("ParseMediaType: %v", err)
}
boundary := params["boundary"]
if !strings.HasPrefix(boundary, "--") {
log.Fatalf("expected boundary to start with --, got %q", boundary)
}
r := multipart.NewReader(res.Body, boundary[2:])
framec := make(chan image.Image, 10)
go decodeFrames(framec, r)
win, err := x11.NewWindow()
if err != nil {
log.Fatalf("NewWindow: %v", err)
}
eventc := win.EventChan()
for {
select {
case evt, ok := <-eventc:
if !ok {
return
}
log.Printf("Event: %#v", evt)
case im := <-framec:
log.Printf("frame")
sim := win.Screen()
draw.Draw(sim, im.Bounds(), im, sim.Bounds().Min, draw.Over)
if *flush {
win.FlushImage()
}
}
}
}
func decodeFrames(c chan image.Image, r *multipart.Reader) {
for {
p, err := r.NextPart()
if err != nil {
log.Fatalf("NextPart: %v", err)
}
im, err := jpeg.Decode(p)
if err != nil {
log.Fatalf("jpeg Decode: %v", err)
}
c <- im
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment