ref: d696956ababd5fdec5bcb51373896468c310161d
dir: /stream_mc.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "stream.h" #include "misc.h" enum { Maxstreams = 3, Bufsz = 64*1024, }; typedef struct MCaux MCaux; struct MCaux { int fd; Biobuf bio; u8int buf[Bufsz]; }; extern uvlong trackpref; 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 void freeaux(void *aux) { MCaux *a; a = aux; close(a->fd); free(a); } static Stream * mcopen(char *filename, int *num, int *failed) { Waitmsg *w; char *line; int p, pid, n, ns; Biobuf b; MCaux *a; char *argv[] = { "mcfs", filename, nil, nil, nil, }; Stream *s, *streams; int nvideo, naudio, nsub, 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 = nsub = 0; ns < Maxstreams && (line = Brdstr(&b, '\n', 1)) != nil;){ n = tokenize(line, v, nelem(v)); if(trackpref != 0 && (trackpref & (1<<atoi(v[0]))) == 0) continue; if(n >= 3 && str2fmt(v[2]) >= 0){ argv[1] = "-t"; argv[2] = v[0]; /* stream id */ argv[3] = filename; s = streams+ns; if(n >= 5 && nvideo < 1 && strcmp(v[1], "video") == 0){ s->video.w = atoi(v[3]); s->video.h = atoi(v[4]); if(mcfs(argv, &sp) > 0){ if((a = malloc(sizeof(*a))) == nil) sysfatal("memory"); a->fd = sp; s->aux = a; s->freeaux = freeaux; if(Binits(&a->bio, sp, OREAD, a->buf, Bufsz) == 0 && ivfopenb(&a->bio, s, failed) == 0){ nvideo++; ns++; } } }else if(n >= 5 && naudio < 1 && strcmp(v[1], "audio") == 0 && (s->fmt = str2fmt(v[2])) >= 0){ s->audio.nchan = atoi(v[3]); s->audio.srate = atoi(v[4]); snprint(s->info, sizeof(s->info), "%s (%d %d)", v[2], s->audio.nchan, s->audio.srate); if(mcfs(argv, &sp) > 0 && audopenfd(sp, s, failed) == 0){ naudio++; ns++; } }else if(n >= 3 && nsub < 1 && strcmp(v[1], "subtitle") == 0 && (s->fmt = str2fmt(v[2])) >= 0){ snprint(s->info, sizeof(s->info), "%s (%s)", v[2], (n > 3 && *v[3]) ? v[3] : "default"); if(mcfs(argv, &sp) > 0 && subopenfd(sp, s, failed) == 0){ nsub++; ns++; } } } free(line); } Bterm(&b); *num = ns; if(ns < 1){ werrstr("no supported video 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, };