ref: 063050e9aa438f4e88db813d1377b569a442de19
dir: /stream_mc.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "stream.h" #include "misc.h" enum { Maxstreams = 2, }; static int mcfs(char **argv, int *pipefd) { int p[2], pid; pipe(p); if((pid = rfork(RFFDG|RFPROC)) == 0){ close(0); close(p[0]); dup(p[1], 1); close(p[1]); exec("/bin/mcfs", argv); sysfatal("exec: %r"); } close(p[1]); if(pid < 0) close(p[0]); *pipefd = p[0]; return pid; } static int audfmt(char *fmt) { static char *fmts[] = { [FmtAAC] = "aac", [FmtOpus] = "opus", [FmtVorbis] = "vorbis", }; int i; for(i = 0; i < nelem(fmts); i++){ if(fmts[i] != nil && strcmp(fmt, fmts[i]) == 0) return i; } return -1; } static Stream * mcopen(char *filename, int *num, int *failed) { Waitmsg *w; char *line; int p, pid, n, ns; Biobuf b; char *argv[] = { "mcfs", filename, nil, nil, nil, }; Stream *s, *streams; int nvideo, naudio, sp; char *v[8]; if((pid = mcfs(argv, &p)) < 0) return nil; if((streams = calloc(Maxstreams, sizeof(Stream))) == nil) return nil; Binit(&b, p, OREAD); for(ns = naudio = nvideo = 0; ns < Maxstreams && (line = Brdstr(&b, '\n', 1)) != nil;){ n = tokenize(line, v, nelem(v)); if(n > 4 && str2fmt(v[2]) >= 0){ argv[1] = "-t"; argv[2] = v[0]; /* stream id */ argv[3] = filename; s = streams+ns; if(nvideo < 1 && strcmp(v[1], "video") == 0){ s->video.w = atoi(v[3]); s->video.h = atoi(v[4]); if(mcfs(argv, &sp) > 0 && ivfopenb(Bfdopen(sp, OREAD), s, failed) == 0){ nvideo++; ns++; } }else if(naudio < 1 && strcmp(v[1], "audio") == 0 && (s->fmt = audfmt(v[2])) >= 0){ s->audio.nchan = atoi(v[3]); s->audio.srate = atoi(v[4]); if(mcfs(argv, &sp) > 0 && audopenfd(sp, s, failed) == 0){ naudio++; ns++; } } } free(line); } Bterm(&b); *num = ns; if(ns < 1){ werrstr("no streams"); *failed = 1; free(streams); streams = nil; while((w = wait()) != nil){ if(w->pid == pid){ if(w->msg[0] != 0){ werrstr("%s", w->msg); goto err; } free(w); break; } free(w); } } return streams; err: free(w); free(streams); return nil; } Streamops mcops = { .open = mcopen, };