//Creating a thumbnail from a mp4 is complex so I cheat and use FFMPEG to create a JPEG... //JPEG is straightforwards // but ffmpeg probably can't make a thumbnail from a piped reader, so this only works if our //ReadSeeker is actually an *os.File func (m *Mp4Video) Thumbnail(in io.ReadSeeker, longSide int) (io.ReadSeeker, string, error) { var cmd *exec.Cmd if file, ok := in.(*os.File); ok { //this is the best way as ffmpeg can seek. cmd = exec.Command("ffmpeg", "-i", "/dev/fd/3", "-vframes", "1", "-f", "image2", "-") cmd.ExtraFiles = []*os.File{file} } else { log.Println("mp4thumb: using stdin (will probably fail...)") cmd = exec.Command("ffmpeg", "-i", "-", "-vframes", "1", "-f", "image2", "-") cmd.Stdin = in } stdout, err := cmd.StdoutPipe() //cmd.Stderr = os.Stderr if err != nil { return nil, "", err } if err := cmd.Start(); err != nil { return nil, "", err } img, err := jpeg.Decode(stdout) if err != nil { return nil, "", err } if err := cmd.Wait(); err != nil { return nil, "", err } //now we should have a jpeg to resize! var w, h int aspect := float64(m.Width) / float64(m.Height) if m.Width > m.Height { w, h = longSide, int(float64(longSide)/aspect) } else { w, h = int(float64(longSide)*aspect), longSide } switch m.Orientation { case photo.OrientedNormal90, photo.OrientedNormal270: //flip then rotate 270 w, h = h, w } //now create thumbnail. img = imaging.Thumbnail(img, w, h, imaging.Box) //rotate if needed. switch m.Orientation { case photo.OrientedNormal90: //rotate 90 (270 anticlockwise) img = imaging.Rotate270(img) case photo.OrientedNormal180: //rotate 180 img = imaging.Rotate180(img) case photo.OrientedNormal270: //rotate 270 (90 anti-clockwise) img = imaging.Rotate90(img) } var wr bytes.Buffer err = jpeg.Encode(&wr, img, nil) return bytes.NewReader(wr.Bytes()), "image/jpeg", err }
func (w *Wirer) Wire(cmd *exec.Cmd) (*os.File, *os.File, *os.File, *os.File, error) { extraFdR, extraFdW, err := os.Pipe() if err != nil { return nil, nil, nil, nil, err } cmd.ExtraFiles = []*os.File{extraFdR} var stdinW, stdoutR, stderrR *os.File if w.WithTty { cmd.Stdin, stdinW, stdoutR, cmd.Stdout, stderrR, cmd.Stderr, err = createTtyPty(w.WindowColumns, w.WindowRows) cmd.SysProcAttr.Setctty = true cmd.SysProcAttr.Setsid = true } else { cmd.Stdin, stdinW, stdoutR, cmd.Stdout, stderrR, cmd.Stderr, err = createPipes() } return stdinW, stdoutR, stderrR, extraFdW, nil }
func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) { cmd.ExtraFiles = append(cmd.ExtraFiles, comm.f) cmd.ExtraFiles = append(cmd.ExtraFiles, rOut) cmd.ExtraFiles = append(cmd.ExtraFiles, wIn) }
func (d *ExecRunner) Run(log lager.Logger, spec *runrunc.PreparedSpec, processesPath, handle string, tty *garden.TTYSpec, pio garden.ProcessIO) (p garden.Process, theErr error) { log = log.Session("execrunner") log.Info("start") defer log.Info("done") processID := d.processIDGen.Generate() processPath := filepath.Join(processesPath, processID) if err := os.MkdirAll(processPath, 0700); err != nil { return nil, err } fd3r, fd3w, err := os.Pipe() if err != nil { return nil, err } logr, logw, err := os.Pipe() if err != nil { return nil, err } syncr, syncw, err := os.Pipe() if err != nil { return nil, err } defer fd3r.Close() defer logr.Close() defer syncr.Close() process := newProcess(processID, processPath, filepath.Join(processPath, "pidfile"), d.pidGetter) process.mkfifos() if err != nil { return nil, err } var cmd *exec.Cmd if tty != nil { var rows, cols int if tty.WindowSize != nil { rows = tty.WindowSize.Rows cols = tty.WindowSize.Columns } cmd = exec.Command(d.dadooPath, "-tty", "-rows", strconv.Itoa(rows), "-cols", strconv.Itoa(cols), "-uid", strconv.Itoa(spec.HostUID), "-gid", strconv.Itoa(spec.HostGID), "exec", d.runcPath, processPath, handle) } else { cmd = exec.Command(d.dadooPath, "exec", d.runcPath, processPath, handle) } cmd.ExtraFiles = []*os.File{ fd3w, logw, syncw, } encodedSpec, err := json.Marshal(spec.Process) if err != nil { return nil, err // this could *almost* be a panic: a valid spec should always encode (but out of caution we'll error) } cmd.Stdin = bytes.NewReader(encodedSpec) if err := d.commandRunner.Start(cmd); err != nil { return nil, err } go d.commandRunner.Wait(cmd) // wait on spawned process to avoid zombies fd3w.Close() logw.Close() syncw.Close() stdin, stdout, stderr, err := process.openPipes(pio) if err != nil { return nil, err } syncMsg := make([]byte, 1) _, err = syncr.Read(syncMsg) if err != nil { return nil, err } process.streamData(pio, stdin, stdout, stderr) defer func() { theErr = processLogs(log, logr, theErr) }() log.Info("read-exit-fd") runcExitStatus := make([]byte, 1) fd3r.Read(runcExitStatus) log.Info("runc-exit-status", lager.Data{"status": runcExitStatus[0]}) if runcExitStatus[0] != 0 { return nil, fmt.Errorf("exit status %d", runcExitStatus[0]) } return process, nil }
func startInstance(cmd *exec.Cmd, r *os.File, w *os.File) error { cmd.ExtraFiles = []*os.File{r, w} return cmd.Start() }