ref: 98ff0d3b979916a86e675557021c485ee07ba04b
parent: b4ab00e016ba0b1b30bc8a58698287f9e2b0afdb
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Sep 16 11:13:47 EDT 2020
add VP8/VP9 decoding
--- a/README.md
+++ b/README.md
@@ -14,6 +14,10 @@
supported atm. AAC audio is supported (inside and outside of a
container). OPUS audio is supported outside of a container.
+It can play VP8 and VP9, but no support for webm/matroska has been
+added yet to mcfs, so treason can only play a VP8/VP9 video stream
+muxed as IVF as of now.
+
*It's only supposed to build and run on AMD64 for now.*
More is coming. Patches are very welcome, too.
@@ -24,11 +28,13 @@
cd /tmp
git/clone https://git.sr.ht/~ft/dav1d
+ git/clone https://git.sr.ht/~ft/faad2
git/clone https://git.sr.ht/~ft/h264bsd
- git/clone https://git.sr.ht/~ft/treason
+ git/clone https://git.sr.ht/~ft/libvpx
git/clone https://git.sr.ht/~ft/mcfs
- git/clone https://git.sr.ht/~ft/faad2
- cd dav1d/src && mk
+ git/clone https://git.sr.ht/~ft/treason
+ cd libvpx && mk
+ cd ../dav1d/src && mk
cd ../../h264bsd/src && mk install
cd ../../treason && mk install
cd ../mcfs && mk install
--- a/decoder.c
+++ b/decoder.c
@@ -5,7 +5,7 @@
#include "decoder.h"
#include "frame.h"
-extern Decoderops av1ops, h264ops;
+extern Decoderops av1ops, h264ops, vpxops;
static struct {
char *name;
@@ -14,6 +14,8 @@
}ops[] = {
{"AV1", &av1ops, FmtAV1},
{"H264", &h264ops, FmtH264},
+ {"VP8", &vpxops, FmtVP8},
+ {"VP9", &vpxops, FmtVP9},
};
Decoder *
--- a/decoder_h264.c
+++ b/decoder_h264.c
@@ -31,7 +31,6 @@
d = x;
a = d->aux;
lasttimestamp = 0;
- memset(&pic, 0, sizeof(pic));
realh = 0;
for(res = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0;){
off = 0;
--- /dev/null
+++ b/decoder_vpx.c
@@ -1,0 +1,104 @@
+#include <vpx_codec.h>
+#include <vpx_decoder.h>
+#include <vpx_image.h>
+#include <vp8dx.h>
+#include "frame.h"
+#include "stream.h"
+#include "decoder.h"
+#include "misc.h"
+
+#pragma lib "../libvpx/libvpx.a"
+
+typedef struct Aux Aux;
+
+struct Aux {
+ vpx_codec_ctx_t ctx;
+};
+
+static void
+decode(void *x)
+{
+ uvlong lasttimestamp;
+ Decoder *d;
+ Channel *c;
+ Frame *f;
+ Streamframe sf;
+ Aux *a;
+ int res;
+ u8int *pic;
+ vpx_codec_iter_t iter;
+ vpx_image_t *im;
+
+ threadsetname("decoder/vpx");
+ 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;){
+ if((res = vpx_codec_decode(&a->ctx, sf.buf, sf.sz, NULL, 0)) != 0){
+ werrstr("vpx_codec_decode failed");
+ break;
+ }
+
+ for(iter = nil;;){
+ if((im = vpx_codec_get_frame(&a->ctx, &iter)) == nil)
+ break;
+
+ if((f = malloc(sizeof(*f) + im->w*im->h*3)) != nil){
+ f->w = im->w;
+ f->h = im->h;
+ yuv420_rgb24(im->w, im->h, im->planes[0], im->planes[1], im->planes[2], im->stride[0], im->stride[1], f->rgb, f->w*3);
+ f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
+ lasttimestamp = sf.timestamp;
+
+ if(sendp(d->frames, f) < 0){
+ free(f);
+ goto done;
+ }
+ }
+ }
+ }
+ if(res != 0)
+ fprint(2, "vpx: %r\n");
+
+done:
+ vpx_codec_destroy(&a->ctx);
+ free(a);
+ c = d->finished;
+ sendp(c, res == 0 ? nil : "error");
+ chanclose(c);
+
+ threadexits(nil);
+}
+
+static int
+vpxopen(Decoder *d)
+{
+ Aux *a;
+ vpx_codec_iface_t *iface;
+
+ a = calloc(1, sizeof(*a));
+ iface = d->s->fmt == FmtVP9 ? vpx_codec_vp9_dx() : vpx_codec_vp8_dx();
+
+ if(vpx_codec_dec_init(&a->ctx, iface, nil, 0) != 0){
+ werrstr("vpx_codec_dec_init failed");
+ free(a);
+ return -1;
+ }
+
+ d->aux = a;
+ proccreate(decode, d, 65536);
+
+ return 0;
+}
+
+static void
+vpxclose(Decoder *d)
+{
+ USED(d);
+}
+
+Decoderops vpxops = {
+ .open = vpxopen,
+ .close = vpxclose,
+};
--- a/mkfile
+++ b/mkfile
@@ -1,7 +1,7 @@
</$objtype/mkfile
TARG=treason
-CFLAGS=$CFLAGS -D__plan9__ -p -I../dav1d/include/dav1d -I../dav1d/src/plan9 -I../h264bsd/src
+CFLAGS=$CFLAGS -D__plan9__ -p -I../dav1d/include/dav1d -I../libvpx/vpx -I../dav1d/src/plan9 -I../h264bsd/src
BIN=/$objtype/bin
HFILES=\
@@ -14,6 +14,7 @@
decoder.$O\
decoder_av1.$O\
decoder_h264.$O\
+ decoder_vpx.$O\
main.$O\
misc.$O\
stream.$O\
--- a/stream.c
+++ b/stream.c
@@ -8,8 +8,8 @@
char *name;
Streamops *o;
}ops[] = {
- {"mc", &mcops},
{"ivf", &ivfops},
+ {"mc", &mcops},
{"audio", &audops},
};