ref: 0ec0e4fde657c442431548180c91018078c2bf3c
dir: /main.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <bio.h> #include "ivf.h" #include "flv.h" #include "rtmp.h" int mainstacksize = 65536; static void usage(void) { fprint(2, "usage: %s [-a AUDIO] -v VIDEO [URL]\n", argv0); threadexitsall("usage"); } void threadmain(int argc, char **argv) { Biobuf *a, *v, o; u8int *b, *p, *e; int bufsz; u64int ns; IVFrame f; IVF ivf; RTMP *r; a = nil; v = nil; ARGBEGIN{ case 'a': if((a = Bopen(EARGF(usage()), OREAD)) == nil) sysfatal("%r"); break; case 'v': if((v = Bopen(EARGF(usage()), OREAD)) == nil) sysfatal("%r"); break; default: usage(); }ARGEND if(argc != 1) usage(); if(v == nil) sysfatal("no video specified"); if(ivfopen(v, &ivf) != 0) sysfatal("%r"); if(strcmp(ivf.type, "AVC1") != 0) sysfatal("not H.264"); srand(time(nil)); if((r = rtmpdial(argv[0])) < 0 || Binit(&o, fd, OWRITE) < 0) sysfatal("%r"); bufsz = 65536; if((b = malloc(bufsz)) == nil) sysfatal("memory"); e = b + bufsz; if((p = flvscript(b, e, ivf.w, ivf.h, 0)) == nil || Bwrite(&o, b, p-b) < 0) sysfatal("%r"); memset(&f, 0, sizeof(f)); for(;;){ if(ivfread(v, &f) != 0) sysfatal("%r"); if(f.sz == 0) break; if(bufsz < f.sz+64){ free(b); bufsz *= 2; if((b = malloc(bufsz)) == nil) sysfatal("memory"); e = b + bufsz; } ns = ivfns(&ivf, f.ts); if((p = flvdata(b, e, ns, ns, f.buf, f.sz, Fvideo, FlHdr)) == nil) sysfatal("video: flvdata: %r"); if(Bwrite(&o, b, p-b) < 0) sysfatal("%r"); Bflush(&o); } threadexitsall(nil); }