shithub: treason

Download patch

ref: ed1cdb97219e38a58059984894d1bed4556776af
parent: f8f4444cde638c762dc175508f19dd1b5cb6f7fc
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Sep 15 10:18:38 EDT 2020

add h.264 baseline support

--- a/README.md
+++ b/README.md
@@ -8,13 +8,16 @@
 
 [Video two](https://diode.zone/videos/watch/4f16e664-8701-4125-a62c-9137f3b4a4da)
 
-It can play [AV1](https://en.wikipedia.org/wiki/AV1)-encoded MP4 files
-on AMD64 machines.  Only 8-bit per component YUV 4:2:0 is supported
-atm.  AAC audio is supported (inside and outside of a container).
-OPUS audio is supported outside a container.
+What can it play?  MP4 files, which are multimedia containers.  Video
+formats supported are [AV1](https://en.wikipedia.org/wiki/AV1) and
+H.264 (baseline only).  Only 8-bit per component YUV 4:2:0 is
+supported atm.  AAC audio is supported (inside and outside of a
+container).  OPUS audio is supported outside of a container.
 
-More is coming soon.
+It's only supposed to build and run on AMD64 for now.
 
+More is coming. Patches are very welcome, too.
+
 ## Installing
 
 Install (or update) [git9](https://github.com/oridb/git9), then:
@@ -21,10 +24,12 @@
 
 	cd /tmp
 	git/clone https://git.sr.ht/~ft/dav1d
+	git/clone https://git.sr.ht/~ft/h264bsd
 	git/clone https://git.sr.ht/~ft/treason
 	git/clone https://git.sr.ht/~ft/mcfs
 	git/clone https://git.sr.ht/~ft/faad2
 	cd dav1d/src && mk
+	cd ../../h264bsd/src && mk install
 	cd ../../treason && mk install
 	cd ../mcfs && mk install
 	cd ../faad2/libfaad && mk install && cd ../frontend && mk install
@@ -36,8 +41,6 @@
 Vesa video driver? No.
 
 Drawterm? No.
-
-There is nothing that keeps the audio in sync with the video atm.
 
 ## Contact
 
--- a/decoder.c
+++ b/decoder.c
@@ -5,7 +5,7 @@
 #include "decoder.h"
 #include "frame.h"
 
-extern Decoderops av1ops;
+extern Decoderops av1ops, h264ops;
 
 static struct {
 	char *name;
@@ -13,6 +13,7 @@
 	int fmt;
 }ops[] = {
 	{"AV1", &av1ops, FmtAV1},
+	{"H264", &h264ops, FmtH264},
 };
 
 Decoder *
--- /dev/null
+++ b/decoder_h264.c
@@ -1,0 +1,128 @@
+#include <h264bsd_decoder.h>
+#include <h264bsd_util.h>
+#include <thread.h>
+#include "frame.h"
+#include "stream.h"
+#include "decoder.h"
+#include "misc.h"
+
+#pragma lib "../h264bsd/src/libh264bsd.$M.a"
+
+typedef struct Aux Aux;
+
+struct Aux {
+	storage_t c;
+};
+
+static void
+decode(void *x)
+{
+	uvlong lasttimestamp;
+	Decoder *d;
+	Channel *c;
+	Frame *f;
+	Streamframe sf;
+	Aux *a;
+	int res, off;
+	u32int used, nerr, isidr, picid;
+	u32int w, h, crop, left, top;
+	u8int *pic;
+
+	d = x;
+	a = d->aux;
+	lasttimestamp = 0;
+	memset(&pic, 0, sizeof(pic));
+	for(res = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0;){
+		off = 0;
+next:
+		if((res = h264bsdDecode(&a->c, sf.buf+off, sf.sz-off, 0, &used)) < 0){
+			werrstr("h264bsdDecode: %d", res);
+			break;
+		}
+		off += used;
+		switch(res){
+		case H264BSD_PIC_RDY:
+			if((pic = h264bsdNextOutputPicture(&a->c, &picid, &isidr, &nerr)) == nil){
+				werrstr("nil pic");
+				res = -1;
+			}else if((f = malloc(sizeof(*f) + w*h*3)) != nil){
+				f->w = w;
+				f->h = h;
+				/* FIXME I have not a single idea what are these weird shifts based on image width */
+				yuv420_rgb24(w, h, pic, pic+w*h+w*8, pic+w*h*5/4+w*10, w, w/2, f->rgb, w*3);
+				f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
+				lasttimestamp = sf.timestamp;
+
+				if(sendp(d->frames, f) < 0){
+					free(f);
+					goto done;
+				}
+			}
+			break;
+
+		case H264BSD_HDRS_RDY:
+			h264bsdCroppingParams(&a->c, &crop, &left, &w, &top, &h);
+			if(!crop){
+				w = h264bsdPicWidth(&a->c) * 16;
+				h = h264bsdPicHeight(&a->c) * 16;
+			}
+			break;
+
+		case H264BSD_RDY:
+			break;
+
+		case H264BSD_ERROR:
+	        res = -1;
+			werrstr("H264BSD_ERROR");
+			break;
+
+		case H264BSD_PARAM_SET_ERROR:
+	        res = -1;
+			werrstr("H264BSD_PARAM_SET_ERROR");
+			break;
+		}
+
+		if(off < sf.sz)
+			goto next;
+	}
+	if(res != 0)
+		fprint(2, "h264: %r\n");
+
+done:
+	h264bsdShutdown(&a->c);
+	free(a);
+	c = d->finished;
+	sendp(c, nil);
+	chanclose(c);
+
+	threadexits(nil);
+}
+
+static int
+h264open(Decoder *d)
+{
+	Aux *a;
+	int res;
+
+	a = calloc(1, sizeof(*a));
+	if((res = h264bsdInit(&a->c, HANTRO_FALSE)) != 0){
+		werrstr("h264bsdInit: %d", res);
+		free(a);
+		return -1;
+	}
+	d->aux = a;
+	proccreate(decode, d, 65536);
+
+	return res;
+}
+
+static void
+h264close(Decoder *d)
+{
+	USED(d);
+}
+
+Decoderops h264ops = {
+	.open = h264open,
+	.close = h264close,
+};
--- a/misc.c
+++ b/misc.c
@@ -10,6 +10,7 @@
 	[FmtAV1]  = "av01",
 	[FmtVP9]  = "vp09",
 	[FmtVP8]  = "vp08",
+	[FmtH264] = "avc1",
 	[FmtAAC]  = "mp4a",
 	[FmtOpus] = "opus",
 };
--- a/mkfile
+++ b/mkfile
@@ -1,7 +1,7 @@
 </$objtype/mkfile
 
 TARG=treason
-CFLAGS=$CFLAGS -p -I../dav1d/include/dav1d -I../dav1d/src/plan9
+CFLAGS=$CFLAGS -D__plan9__ -p -I../dav1d/include/dav1d -I../dav1d/src/plan9 -I../h264bsd/src
 BIN=/$objtype/bin
 
 HFILES=\
@@ -13,6 +13,7 @@
 OFILES=\
 	decoder.$O\
 	decoder_av1.$O\
+	decoder_h264.$O\
 	main.$O\
 	misc.$O\
 	stream.$O\
--- a/stream.h
+++ b/stream.h
@@ -13,6 +13,7 @@
 	FmtAV1 = 0,
 	FmtVP9,
 	FmtVP8,
+	FmtH264,
 	/* audio */
 	FmtAAC,
 	FmtOpus,
--- a/stream_ivf.c
+++ b/stream_ivf.c
@@ -83,6 +83,8 @@
 		fmt = FmtVP9;
 	else if(memcmp(tmp, "VP80", 4) == 0)
 		fmt = FmtVP8;
+	else if(memcmp(tmp, "AVC1", 4) == 0) /* FIXME that's non-standard */
+		fmt = FmtH264;
 	else{
 		werrstr("unsupported format %.*s", 4, tmp);
 		goto err;