shithub: treason

Download patch

ref: 1467915184ce4df4e1754bd7efabd61b13fea47e
parent: 71687b06891fe7024fa66a0ee8d47769d05c11ed
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Fri Dec 11 04:39:17 EST 2020

use openh264

--- a/decoder_h264.c
+++ b/decoder_h264.c
@@ -1,5 +1,4 @@
-#include <h264bsd_decoder.h>
-#include <h264bsd_util.h>
+#include <decoder/core/inc/decoder.h>
 #include <thread.h>
 #include "frame.h"
 #include "stream.h"
@@ -6,15 +5,157 @@
 #include "decoder.h"
 #include "misc.h"
 
-#pragma lib "../h264bsd/src/libh264bsd.$M.a"
+#pragma lib "../openh264/codec/libopenh264.a"
 
 typedef struct Aux Aux;
 
 struct Aux {
-	storage_t c;
+	SWelsDecoderContext ctx;
+	SLogContext logctx;
+	SBufferInfo info;
+	SWelsLastDecPicInfo pic;
+	SVlcTable vlctbl;
+	SDecoderStatistics stat;
+	uint8_t *data[3];
+
+	/* reordering */
+	SPictInfo pics[16];
+	int npics;
+	int lastgopremain;
+	int lastbuffered;
+	int lastwritten;
+	int lbufpicind;
+	int minpoc;
+	int picind;
 };
 
 static void
+logfun(void *pCtx, const int32_t iLevel, const char *kpFmt, va_list argv)
+{
+	USED(pCtx, iLevel);
+/*
+	fprint(2, "h264: ");
+	vfprint(2, kpFmt, argv);
+	fprint(2, "\n");
+*/
+	USED(kpFmt, argv);
+}
+
+static void
+reorder(Aux *a)
+{
+	int i, firstvalid;
+
+	if(a->npics && a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb && a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin){
+		a->lastgopremain = a->npics;
+
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(a->pics[i].iPOC > IMinInt32)
+				a->pics[i].bLastGOP = true;
+		}
+	}else if(a->npics > 0){
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(a->pics[i].iPOC == a->ctx.pSliceHeader->iPicOrderCntLsb){
+				a->lastgopremain = a->npics;
+				for(i = 0; i <= a->lbufpicind; i++){
+					if (a->pics[i].iPOC > IMinInt32)
+						a->pics[i].bLastGOP = true;
+				}
+				break;
+			}
+		}
+	}
+
+	for(i = 0; i < nelem(a->pics); i++){
+		if(a->pics[i].iPOC == IMinInt32){
+			memmove(&a->pics[i].sBufferInfo, &a->info, sizeof (SBufferInfo));
+			a->pics[i].iPOC = a->ctx.pSliceHeader->iPicOrderCntLsb;
+			a->pics[i].uiDecodingTimeStamp = a->ctx.uiDecodingTimeStamp;
+			a->pics[i].iPicBuffIdx = a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
+			a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount++;
+			a->pics[i].bLastGOP = false;
+			a->lastbuffered = i;
+			a->info.iBufferStatus = 0;
+			a->npics++;
+			if(i > a->lbufpicind)
+				a->lbufpicind = i;
+			break;
+		}
+	}
+
+	PPicBuff pPicBuff = a->ctx.pPicBuff;
+	if(a->lastgopremain > 0){
+		a->minpoc = IMinInt32;
+		firstvalid = -1;
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(a->minpoc == IMinInt32 && a->pics[i].iPOC > IMinInt32 && a->pics[i].bLastGOP){
+				a->minpoc = a->pics[i].iPOC;
+				a->picind = i;
+				firstvalid = i;
+				break;
+			}
+		}
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(i == firstvalid)
+				continue;
+			if(a->pics[i].iPOC > IMinInt32 && a->pics[i].iPOC < a->minpoc && a->pics[i].bLastGOP){
+				a->minpoc = a->pics[i].iPOC;
+				a->picind = i;
+			}
+		}
+		a->lastwritten = a->minpoc;
+		memmove(&a->info, &a->pics[a->picind].sBufferInfo, sizeof (SBufferInfo));
+		a->data[0] = a->info.pDst[0];
+		a->data[1] = a->info.pDst[1];
+		a->data[2] = a->info.pDst[2];
+		a->pics[a->picind].iPOC = IMinInt32;
+		PPicture pPic = pPicBuff->ppPic[a->pics[a->picind].iPicBuffIdx];
+		pPic->iRefCount--;
+		a->pics[a->picind].bLastGOP = false;
+		a->minpoc = IMinInt32;
+		a->npics--;
+		a->lastgopremain--;
+		if(a->lastgopremain == 0)
+			a->lastwritten = IMinInt32;
+		return;
+	}
+
+	if(a->npics > 0){
+		a->minpoc = IMinInt32;
+		firstvalid = -1;
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(a->minpoc == IMinInt32 && a->pics[i].iPOC > IMinInt32){
+				a->minpoc = a->pics[i].iPOC;
+				a->picind = i;
+				firstvalid = i;
+				break;
+			}
+		}
+		for(i = 0; i <= a->lbufpicind; i++){
+			if(i == firstvalid)
+				continue;
+			if(a->pics[i].iPOC > IMinInt32 && a->pics[i].iPOC < a->minpoc){
+				a->minpoc = a->pics[i].iPOC;
+				a->picind = i;
+			}
+		}
+	}
+	if(a->minpoc > IMinInt32 && (a->lastwritten > IMinInt32 && a->minpoc - a->lastwritten <= 1) || a->minpoc < a->ctx.pSliceHeader->iPicOrderCntLsb){
+		a->lastwritten = a->minpoc;
+		memmove(&a->info, &a->pics[a->picind].sBufferInfo, sizeof (SBufferInfo));
+		a->data[0] = a->info.pDst[0];
+		a->data[1] = a->info.pDst[1];
+		a->data[2] = a->info.pDst[2];
+		a->pics[a->picind].iPOC = IMinInt32;
+		PPicture pPic = pPicBuff->ppPic[a->pics[a->picind].iPicBuffIdx];
+		pPic->iRefCount--;
+		a->pics[a->picind].bLastGOP = false;
+		a->minpoc = IMinInt32;
+		a->npics--;
+	}
+}
+
+static void
 decode(void *x)
 {
 	uvlong lasttimestamp;
@@ -23,83 +164,52 @@
 	Frame *f;
 	Streamframe sf;
 	Aux *a;
-	int res, off;
-	u32int used, nerr, isidr, picid;
-	u32int realw, realh, w, h, crop, left, top;
-	u8int *pic;
+	int res, w, h, *stride;
 
 	d = x;
 	a = d->aux;
 	lasttimestamp = 0;
-	realw = 0;
-	realh = 0;
 	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: %r (%d)", res);
+		if((res = WelsDecodeBs(&a->ctx, sf.buf, sf.sz, a->data, &a->info, nil)) != 0){
+			werrstr("WelsDecodeBs: error %#x", 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 = realh;
-				f->crop.left = left;
-				f->crop.top = top;
-				f->crop.right = realw;
-				f->crop.bottom = realh;
-				yuv420_rgb24(w, h, pic, pic+w*h, pic+w*h*5/4, w, w/2, f->rgb, w*3);
-				f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
-				lasttimestamp = sf.timestamp;
+		if(a->info.iBufferStatus == 0)
+			continue;
 
-				if(sendp(d->frames, f) < 0){
-					free(f);
-					goto done;
-				}
-			}
-			break;
+		if(a->ctx.pSps->uiProfileIdc != 66 && a->ctx.pSps->uiProfileIdc != 83){
+			/* non-baseline needs reordering */
+			reorder(a);
+			if(a->data[0] == nil)
+				continue;
+		}
 
-		case H264BSD_HDRS_RDY:
-			h264bsdCroppingParams(&a->c, &crop, &left, &w, &top, &h);
-			if(!crop){
-				w = h264bsdPicWidth(&a->c) * 16;
-				h = h264bsdPicHeight(&a->c) * 16;
-			}
-			realw = w;
-			realh = h;
-			if(w & 15)
-				w += 16 - (w & 15);
-			if(h & 15)
-				h += 16 - (h & 15);
-			break;
+		w = a->info.UsrData.sSystemBuffer.iWidth;
+		h = a->info.UsrData.sSystemBuffer.iHeight;
+		if((f = malloc(sizeof(*f) + w*h*3)) == nil)
+			continue;
 
-		case H264BSD_RDY:
-			break;
+		stride = a->info.UsrData.sSystemBuffer.iStride;
+		f->w = w;
+		f->h = h;
+		f->crop.left = a->ctx.sFrameCrop.iLeftOffset;
+		f->crop.top = a->ctx.sFrameCrop.iTopOffset;
+		f->crop.right = a->ctx.sFrameCrop.iRightOffset;
+		f->crop.bottom = a->ctx.sFrameCrop.iBottomOffset;
+		yuv420_rgb24(w, h, a->data[0], a->data[1], a->data[2], stride[0], stride[1], f->rgb, w*3);
+		f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
+		lasttimestamp = sf.timestamp;
 
-		case H264BSD_ERROR:
-	        res = -1;
-	        werrstr("decoding error: %r");
-			break;
-
-		case H264BSD_PARAM_SET_ERROR:
-	        res = -1;
-			werrstr("param set error: %r");
-			break;
+		if(sendp(d->frames, f) < 0){
+			free(f);
+			goto done;
 		}
-
-		if(off < sf.sz)
-			goto next;
 	}
 	if(res != 0)
 		fprint(2, "h264: %r\n");
 
 done:
-	h264bsdShutdown(&a->c);
+	WelsEndDecoder(&a->ctx);
 	free(a);
 	c = d->finished;
 	sendp(c, res == 0 ? nil : "error");
@@ -112,11 +222,26 @@
 h264open(Decoder *d)
 {
 	Aux *a;
-	int res;
+	int res, i;
 
 	a = calloc(1, sizeof(*a));
-	if((res = h264bsdInit(&a->c, HANTRO_FALSE)) != 0){
-		werrstr("h264bsdInit: %d", res);
+	a->ctx.pLastDecPicInfo = &a->pic;
+	a->ctx.pVlcTable = &a->vlctbl;
+	a->ctx.pDecoderStatistics = &a->stat;
+	a->ctx.pMemAlign = &cMemoryAlign;
+	a->logctx.pfLog = logfun;
+	a->ctx.sLogCtx = a->logctx;
+
+	a->ctx.pParam = calloc(1, sizeof(SDecodingParam));
+	a->ctx.pParam->sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+    a->minpoc = IMinInt32;
+    a->lastwritten = IMinInt32;
+    for(i = 0; i < nelem(a->pics); i++)
+      a->pics[i].iPOC = IMinInt32;
+
+	if((res = WelsInitDecoder(&a->ctx, &a->logctx)) != 0){
+		werrstr("WelsInitDecoder: %d", res);
 		free(a);
 		return -1;
 	}
--- a/install.rc
+++ b/install.rc
@@ -19,9 +19,9 @@
 	cd ../..
 }
 
-test -d h264bsd || { hget https://git.sr.ht/~ft/h264bsd/archive/master.tar.gz | tar xz && \
-	mv h264bsd-master h264bsd && \
-	cd h264bsd/src && \
+test -d openh264 || { hget https://git.sr.ht/~ft/openh264/archive/master.tar.gz | tar xz && \
+	mv openh264-master h264bsd && \
+	cd openh264/codec && \
 	mk && \
 	cd ../..
 }
@@ -67,4 +67,4 @@
 
 cd treason && \
 	mk install && \
-	rm -rf ../^(dav1d faad2-master h264bsd libvpx mcfs-master opus libopusenc opusfile opus-tools alienpatch)
+	rm -rf ../^(dav1d faad2-master openh264 libvpx mcfs-master opus libopusenc opusfile opus-tools alienpatch)
--- a/mkfile
+++ b/mkfile
@@ -1,7 +1,11 @@
 </$objtype/mkfile
 
+CFLAGS=$CFLAGS -D__plan9__ -p -D__${objtype}__\
+ -I../dav1d/include/dav1d -I../dav1d/src/plan9\
+ -I../libvpx/vpx\
+ -I../openh264/codec -I../openh264/codec/api/svc -I../openh264/codec/common/inc -I../openh264/codec/decoder/core/inc
+
 TARG=treason
-CFLAGS=$CFLAGS -D__plan9__ -p -I../dav1d/include/dav1d -I../libvpx/vpx -I../dav1d/src/plan9 -I../h264bsd/src
 BIN=/$objtype/bin
 
 HFILES=\