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");