shithub: rtmp

Download patch

ref: 3168be131e24f503aabda0f0bdf690136eaef03b
parent: 74213ea11514c175161cc1a61d48a429845d4624
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Jul 21 07:40:20 EDT 2021

split ivf logic out

--- /dev/null
+++ b/ivf.c
@@ -1,0 +1,123 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "ivf.h"
+
+static int
+Bu16le(Biobuf *b, u16int *o)
+{
+	int x;
+
+	x = Bgetc(b);
+	x |= Bgetc(b)<<8;
+	*o = x;
+	if(x < 0)
+		werrstr("failed to read 2 bytes");
+
+	return x < 0 ? -1 : 0;
+}
+
+static int
+Bu32le(Biobuf *b, u32int *o)
+{
+	int x, i;
+
+	*o = 0;
+	for(i = 0; i < 4; *o |= x<<(i*8), i++){
+		if((x = Bgetc(b)) < 0){
+			werrstr("failed to read 4 bytes");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+Bu64le(Biobuf *b, u64int *o)
+{
+	int x, i;
+
+	*o = 0;
+	for(i = 0; i < 8; *o |= x<<(i*8), i++){
+		if((x = Bgetc(b)) < 0){
+			werrstr("failed to read 8 bytes");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int
+ivfopen(Biobuf *v, IVF *ivf)
+{
+	u16int hlen;
+	u8int b[6];
+
+	if(Bread(v, b, 6) != 6 || Bu16le(v, &hlen) < 0 ||
+	   hlen < 0x20 || memcmp(b, "DKIF", 4) != 0 ||
+	   Bread(v, b, 4) != 4){
+		werrstr("invalid header");
+		goto err;
+	}
+	memmove(ivf->type, b, 4);
+	ivf->type[4] = 0;
+	if(Bu16le(v, &ivf->w) < 0 ||
+	   Bu16le(v, &ivf->h) < 0 ||
+	   Bu32le(v, &ivf->tbdenum) < 0 ||
+	   Bu32le(v, &ivf->tbnum) < 0){
+		werrstr("invalid data");
+		goto err;
+	}
+	if(Bseek(v, hlen, 0) != hlen){
+		werrstr("broken stream");
+		goto err;
+	}
+
+	return 0;
+err:
+	werrstr("ivfopen: %r");
+	return -1;
+}
+
+int
+ivfread(Biobuf *v, IVFrame *f)
+{
+	u8int *buf;
+	u64int ts;
+	u32int sz;
+	int n;
+
+	if(Bu32le(v, &sz) < 0 || Bu64le(v, &ts) < 0 || (int)sz < 0){
+		/* eof */
+		f->sz = 0;
+		return 0;
+	}
+	buf = f->buf;
+	if(sz > f->bufsz){
+		if((buf = realloc(f->buf, sz)) == nil){
+			werrstr("frame is too big: %d bytes", sz);
+			goto err;
+		}
+		f->buf = buf;
+	}
+	if((n = Bread(v, buf, sz)) != sz){
+		werrstr("short read (%d < %d)", n, sz);
+		goto err;
+	}
+	f->buf = buf;
+	f->sz = sz;
+	f->ts = ts;
+
+	return 0;
+err:
+	werrstr("ivfread: %r");
+	return -1;
+}
+
+u64int
+ivfns(IVF *ivf, u64int ts)
+{
+	return ts * ivf->tbnum * 1000000000ULL / ivf->tbdenum;
+}
--- /dev/null
+++ b/ivf.h
@@ -1,0 +1,21 @@
+typedef struct IVF IVF;
+typedef struct IVFrame IVFrame;
+
+struct IVF {
+	u32int tbdenum;
+	u32int tbnum;
+	u16int w;
+	u16int h;
+	char type[6];
+};
+
+struct IVFrame {
+	u64int ts;
+	u8int *buf;
+	int bufsz;
+	int sz;
+};
+
+int ivfopen(Biobuf *v, IVF *ivf);
+int ivfread(Biobuf *v, IVFrame *f);
+u64int ivfns(IVF *ivf, u64int ts);
--- a/mkfile
+++ b/mkfile
@@ -3,7 +3,11 @@
 BIN=/$objtype/bin/video
 TARG=rtmp
 
+HFILES=\
+	ivf.h\
+
 OFILES=\
+	ivf.$O\
 	rtmp.$O\
 
 default:V: all
--- a/rtmp.c
+++ b/rtmp.c
@@ -3,6 +3,7 @@
 #include <thread.h>
 #include <bio.h>
 #include <libsec.h>
+#include "ivf.h"
 
 enum {
 	Port = 1935,
@@ -23,23 +24,10 @@
 	FlHdr = 1<<1,
 
 	Sigsz = 1536,
-};
 
-typedef struct Frame Frame;
-typedef struct IVF IVF;
-
-struct Frame {
-	u64int ts;
-	u8int *buf;
-	int bufsz;
-	int sz;
+	ChanCtl = 3,
 };
 
-struct IVF {
-	u16int w, h;
-	u32int tbdenum, tbnum;
-};
-
 int mainstacksize = 65536;
 
 static u8int *
@@ -253,121 +241,6 @@
 }
 
 static int
-Bu16le(Biobuf *b, u16int *o)
-{
-	int x;
-
-	x = Bgetc(b);
-	x |= Bgetc(b)<<8;
-	*o = x;
-	if(x < 0)
-		werrstr("failed to read 2 bytes");
-
-	return x < 0 ? -1 : 0;
-}
-
-static int
-Bu32le(Biobuf *b, u32int *o)
-{
-	int x, i;
-
-	*o = 0;
-	for(i = 0; i < 4; *o |= x<<(i*8), i++){
-		if((x = Bgetc(b)) < 0){
-			werrstr("failed to read 4 bytes");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int
-Bu64le(Biobuf *b, u64int *o)
-{
-	int x, i;
-
-	*o = 0;
-	for(i = 0; i < 8; *o |= x<<(i*8), i++){
-		if((x = Bgetc(b)) < 0){
-			werrstr("failed to read 8 bytes");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int
-ivfopen(Biobuf *v, IVF *o)
-{
-	u16int hlen;
-	u8int b[6];
-
-	if(Bread(v, b, 6) != 6 || Bu16le(v, &hlen) < 0 ||
-	   hlen < 0x20 || memcmp(b, "DKIF", 4) != 0 ||
-	   Bread(v, b, 4) != 4){
-		werrstr("invalid header");
-		goto err;
-	}
-	if(memcmp(b, "AVC1", 4) != 0){
-		werrstr("not H.264");
-		goto err;
-	}
-	if(Bu16le(v, &o->w) < 0 ||
-	   Bu16le(v, &o->h) < 0 ||
-	   Bu32le(v, &o->tbdenum) < 0 ||
-	   Bu32le(v, &o->tbnum) < 0){
-		werrstr("invalid data");
-		goto err;
-	}
-	if(Bseek(v, hlen, 0) != hlen){
-		werrstr("broken stream");
-		goto err;
-	}
-
-	return 0;
-err:
-	werrstr("ivf: %r");
-	return -1;
-}
-
-static int
-ivfread(Biobuf *v, Frame *f)
-{
-	u8int *buf;
-	u64int ts;
-	u32int sz;
-	int n;
-
-	if(Bu32le(v, &sz) < 0 || Bu64le(v, &ts) < 0 || (int)sz < 0){
-		/* eof */
-		f->sz = 0;
-		return 0;
-	}
-	buf = f->buf;
-	if(sz > f->bufsz){
-		if((buf = realloc(f->buf, sz)) == nil){
-			werrstr("frame is too big: %d bytes", sz);
-			goto err;
-		}
-		f->buf = buf;
-	}
-	if((n = Bread(v, buf, sz)) != sz){
-		werrstr("short read (%d < %d)", n, sz);
-		goto err;
-	}
-	f->buf = buf;
-	f->sz = sz;
-	f->ts = ts;
-
-	return 0;
-err:
-	werrstr("ivf: %r");
-	return -1;
-}
-
-static int
 handshake(int f, char *path)
 {
 	u8int cl[1+Sigsz], sv[1+Sigsz];
@@ -450,7 +323,8 @@
 	Biobuf *a, *v, o;
 	u8int *b, *p, *e;
 	int bufsz, fd;
-	Frame f;
+	u64int ns;
+	IVFrame f;
 	IVF ivf;
 
 	a = nil;
@@ -474,6 +348,8 @@
 		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((fd = rtmpdial(argv[0])) < 0 || Binit(&o, fd, OWRITE) < 0)
 		sysfatal("%r");
@@ -499,7 +375,8 @@
 				sysfatal("memory");
 			e = b + bufsz;
 		}
-		if((p = flvdata(b, e, f.ts, f.ts, f.buf, f.sz, Fvideo, FlHdr)) == nil)
+		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");