ref: 709cb723bba3aa43ba40a5c70dba0b337bae54e2
dir: /stream_mc.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "stream.h"
#include "misc.h"
enum {
Maxstreams = 2,
Bufsz = 64*1024,
};
typedef struct MCaux MCaux;
struct MCaux {
int fd;
Biobuf bio;
u8int buf[Bufsz];
};
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, 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){
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(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++;
}
}
}
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,
};