ref: 0e3eb9212fbe8f606399c87f52cb1e9369eb7d94
parent: eac7952b194921bd8792d5d35675bd7a4721c8cf
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Feb 1 08:55:40 EST 2021
h264: decode just as welc extended(?) decoder logic does, supporting B-frames
--- a/decoder_h264.c
+++ b/decoder_h264.c
@@ -196,6 +196,44 @@
return t+1;
}
+static int
+one(Aux *a, Streamframe *sf)
+{
+ int res;
+
+ if(sf->buf == nil){
+ a->ctx.bEndOfStreamFlag = true;
+ a->ctx.bInstantDecFlag = true;
+ }else{
+ a->ctx.bEndOfStreamFlag = false;
+ }
+ a->ctx.iErrorCode = dsErrorFree;
+ a->ctx.iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL;
+ a->ctx.uiTimeStamp = a->info.uiInBsTimeStamp;
+ memset(&a->info, 0, sizeof(a->info));
+ memset(a->data, 0, sizeof(a->data));
+ a->ctx.bReferenceLostAtT0Flag = false;
+ a->ctx.bCurAuContainLtrMarkSeFlag = false;
+ a->ctx.iFrameNumOfAuMarkedLtr = 0;
+ a->ctx.iFrameNum = -1;
+ a->ctx.iFeedbackTidInAu = -1;
+ a->ctx.iFeedbackNalRefIdc = -1;
+ if((res = WelsDecodeBs(&a->ctx, sf->buf, sf->sz, a->data, &a->info, nil)) != 0){
+ if(a->ctx.iErrorCode & dsOutOfMemory)
+ return 0;
+ werrstr("%s: %.*H", err2s(res), MIN(32, sf->sz), sf->buf);
+ return -1;
+ }
+
+ if(a->info.iBufferStatus != 0 && a->ctx.pSps->uiProfileIdc != 66 && a->ctx.pSps->uiProfileIdc != 83){
+ /* non-baseline needs reordering */
+ memset(a->data, 0, sizeof(a->data));
+ sf->timestamp = reorder(a, sf->timestamp);
+ }
+
+ return 0;
+}
+
static void
decode(void *x)
{
@@ -213,56 +251,42 @@
lasttimestamp = 0;
start = nanosec();
for(res = 0, framenum = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0; framenum++){
- a->ctx.iErrorCode = dsErrorFree;
- a->ctx.iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL;
- a->ctx.uiTimeStamp = a->info.uiInBsTimeStamp;
- memset(&a->info, 0, sizeof(a->info));
- memset(a->data, 0, sizeof(a->data));
- a->ctx.bReferenceLostAtT0Flag = false;
- a->ctx.bCurAuContainLtrMarkSeFlag = false;
- a->ctx.iFrameNumOfAuMarkedLtr = 0;
- a->ctx.iFrameNum = -1;
- a->ctx.iFeedbackTidInAu = -1;
- a->ctx.iFeedbackNalRefIdc = -1;
- if((res = WelsDecodeBs(&a->ctx, sf.buf, sf.sz, a->data, &a->info, nil)) != 0){
- if(a->ctx.iErrorCode & dsOutOfMemory)
- continue;
- werrstr("%s on frame %llud: %.*H", err2s(res), framenum, MIN(32, sf.sz), sf.buf);
- break;
- }
- if(a->info.iBufferStatus == 0)
- continue;
+ if(one(a, &sf) != 0)
+ goto failed;
- if(a->ctx.pSps->uiProfileIdc != 66 && a->ctx.pSps->uiProfileIdc != 83){
- /* non-baseline needs reordering */
- memset(a->data, 0, sizeof(a->data));
- sf.timestamp = reorder(a, sf.timestamp);
- if(a->data[0] == nil)
- continue;
- }
- d->decodetime = nanosec() - start;
+tryagain:
+ if(a->data[0] != nil && sf.timestamp >= lasttimestamp){
+ d->decodetime = nanosec() - start;
- if(sf.timestamp < lasttimestamp) /* this is not supposed to happen unless mcfs is wrong */
- continue;
+ w = a->info.UsrData.sSystemBuffer.iWidth;
+ h = a->info.UsrData.sSystemBuffer.iHeight;
+ stride = a->info.UsrData.sSystemBuffer.iStride;
+ if((f = newframe(w, h, a->data, stride[0], stride[1])) != nil){
+ f->crop.left = a->ctx.sFrameCrop.iLeftOffset;
+ f->crop.top = a->ctx.sFrameCrop.iTopOffset;
+ f->crop.right = w - a->ctx.sFrameCrop.iRightOffset;
+ f->crop.bottom = h - a->ctx.sFrameCrop.iBottomOffset;
+ f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
+ lasttimestamp = sf.timestamp;
- w = a->info.UsrData.sSystemBuffer.iWidth;
- h = a->info.UsrData.sSystemBuffer.iHeight;
- stride = a->info.UsrData.sSystemBuffer.iStride;
- if((f = newframe(w, h, a->data, stride[0], stride[1])) == nil)
- continue;
+ if(sendp(d->frames, f) < 0){
+ free(f);
+ goto done;
+ }
+ }
+ start = nanosec();
+ }
- f->crop.left = a->ctx.sFrameCrop.iLeftOffset;
- f->crop.top = a->ctx.sFrameCrop.iTopOffset;
- f->crop.right = w - a->ctx.sFrameCrop.iRightOffset;
- f->crop.bottom = h - a->ctx.sFrameCrop.iBottomOffset;
- f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
- lasttimestamp = sf.timestamp;
-
- if(sendp(d->frames, f) < 0){
- free(f);
- goto done;
+ if(sf.buf != nil){
+ sf.buf = nil;
+ sf.sz = 0;
+ if(one(a, &sf) != 0){
+failed:
+ werrstr("frame %llud: %r", framenum);
+ break;
+ }
+ goto tryagain;
}
- start = nanosec();
}
if(res != 0)
fprint(2, "h264: %r\n");