ref: 1467915184ce4df4e1754bd7efabd61b13fea47e
parent: 71687b06891fe7024fa66a0ee8d47769d05c11ed
author: Sigrid Solveig Haflínudóttir <[email protected]>
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=\