ref: 44f4ed0d8f048de95984e01e33d34cff27040114
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, fd;
pipe(p);
if((pid = rfork(RFFDG|RFPROC|RFNOMNT)) == 0){
close(0);
close(p[0]);
dup(p[1], 1); close(p[1]);
if(!debug){
dup(fd = open("/dev/null", OWRITE), 2);
close(fd);
}
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] = "mp4a",
[FmtOpus] = "opus",
};
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",
"-i",
filename,
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,
};