shithub: treason

ref: 4812d7f4d60a30404a8f0d0cb1f244ae288387d5
dir: /stream_mp4.c/

View raw version
#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(RFPROC|RFFDG|RFREND)) == 0){
		close(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 Stream *
mp4open(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 *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;

			if(nvideo < 1 && strcmp(v[1], "video") == 0){
				if(mcfs(argv, &sp) > 0 && ivfopenb(Bfdopen(sp, OREAD), streams+ns, failed) == 0){
					nvideo++;
					ns++;
				}
			}else if(naudio < 1 && strcmp(v[1], "audio") == 0){
				/* FIXME add audio streams */
			}
		}
		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 mp4ops = {
	.open = mp4open,
};