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;