shithub: openh264

Download patch

ref: a31395562e9757b7d7fa12bb87b6cc6a3d495a93
parent: 55b3ec0bab55921f5c35ddec92de4742aa0ee346
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Oct 26 19:24:18 EDT 2021

add 9-specific decoder logic

--- a/codec/plan9.c
+++ b/codec/plan9.c
@@ -1,4 +1,220 @@
 #include "decoder.h"
+#include "decoder9.h"
+
+static void
+reorder(H264Aux *a)
+{
+	int i, firstvalid;
+
+	if(a->iNumOfPicts > 0){
+		if(a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb && a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin){
+			a->iLastGOPRemainPicts = a->iNumOfPicts;
+
+			for(i = 0; i <= a->iLargestBufferedPicIndex; i++)
+				a->pics[i].bLastGOP = a->pics[i].iPOC > IMinInt32;
+		}else{
+			for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+				if(a->pics[i].iPOC == a->ctx.pSliceHeader->iPicOrderCntLsb){
+					a->iLastGOPRemainPicts = a->iNumOfPicts;
+					for(i = 0; i <= a->iLargestBufferedPicIndex; i++)
+						a->pics[i].bLastGOP = a->pics[i].iPOC > IMinInt32;
+					break;
+				}
+			}
+		}
+	}
+
+	for(i = 0; i < nelem(a->pics); i++){
+		if(a->pics[i].iPOC == IMinInt32){
+			memmove(&a->pics[i].sBufferInfo, &a->info, sizeof(a->info));
+			a->pics[i].iPOC = a->ctx.pSliceHeader->iPicOrderCntLsb;
+			a->pics[i].iPicBuffIdx = a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
+			a->pics[i].uiDecodingTimeStamp = a->ctx.uiDecodingTimeStamp;
+			a->ctx.pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount++;
+			a->pics[i].bLastGOP = false;
+			a->info.iBufferStatus = 0;
+			a->iNumOfPicts++;
+			if(a->iLargestBufferedPicIndex < i)
+				a->iLargestBufferedPicIndex = i;
+			break;
+		}
+	}
+
+	PPicBuff picbuf = a->ctx.pPicBuff;
+	if(a->iLastGOPRemainPicts > 0){
+		a->iMinPOC = IMinInt32;
+		firstvalid = -1;
+		for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+			if(a->iMinPOC == IMinInt32 && a->pics[i].iPOC > IMinInt32 && a->pics[i].bLastGOP){
+				a->iMinPOC = a->pics[i].iPOC;
+				a->iPictInfoIndex = i;
+				firstvalid = i;
+				break;
+			}
+		}
+		for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+			if(i == firstvalid)
+				continue;
+			if(a->pics[i].iPOC > IMinInt32 && a->pics[i].iPOC < a->iMinPOC && a->pics[i].bLastGOP){
+				a->iMinPOC = a->pics[i].iPOC;
+				a->iPictInfoIndex = i;
+			}
+		}
+		a->iLastWrittenPOC = a->iMinPOC;
+		memmove(&a->info, &a->pics[a->iPictInfoIndex].sBufferInfo, sizeof(a->info));
+		a->data[0] = a->info.pDst[0];
+		a->data[1] = a->info.pDst[1];
+		a->data[2] = a->info.pDst[2];
+		a->pics[a->iPictInfoIndex].iPOC = IMinInt32;
+		picbuf->ppPic[a->pics[a->iPictInfoIndex].iPicBuffIdx]->iRefCount--;
+		a->pics[a->iPictInfoIndex].bLastGOP = false;
+		a->iMinPOC = IMinInt32;
+		a->iNumOfPicts--;
+		a->iLastGOPRemainPicts--;
+		if(a->iLastGOPRemainPicts == 0)
+			a->iLastWrittenPOC = IMinInt32;
+		return;
+	}
+
+	if(a->iNumOfPicts > 0){
+		a->iMinPOC = IMinInt32;
+		firstvalid = -1;
+		for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+			if(a->iMinPOC == IMinInt32 && a->pics[i].iPOC > IMinInt32){
+				a->iMinPOC = a->pics[i].iPOC;
+				a->iPictInfoIndex = i;
+				firstvalid = i;
+				break;
+			}
+		}
+		for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+			if(i == firstvalid)
+				continue;
+			if(a->pics[i].iPOC > IMinInt32 && a->pics[i].iPOC < a->iMinPOC){
+				a->iMinPOC = a->pics[i].iPOC;
+				a->iPictInfoIndex = i;
+			}
+		}
+	}
+
+	if(a->iMinPOC > IMinInt32 && ((a->iLastWrittenPOC > IMinInt32 && a->iMinPOC - a->iLastWrittenPOC <= 1) || a->iMinPOC < a->ctx.pSliceHeader->iPicOrderCntLsb)){
+		a->iLastWrittenPOC = a->iMinPOC;
+		memmove(&a->info, &a->pics[a->iPictInfoIndex].sBufferInfo, sizeof(a->info));
+		a->data[0] = a->info.pDst[0];
+		a->data[1] = a->info.pDst[1];
+		a->data[2] = a->info.pDst[2];
+		a->pics[a->iPictInfoIndex].iPOC = IMinInt32;
+		picbuf->ppPic[a->pics[a->iPictInfoIndex].iPicBuffIdx]->iRefCount--;
+		a->pics[a->iPictInfoIndex].bLastGOP = false;
+		a->iMinPOC = IMinInt32;
+		a->iNumOfPicts--;
+	}
+}
+
+void
+h264flush(H264Aux *a)
+{
+	int i, firstvalid;
+
+	a->iMinPOC = IMinInt32;
+	firstvalid = -1;
+	for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+		if(a->iMinPOC == IMinInt32 && a->pics[i].iPOC > IMinInt32){
+			a->iMinPOC = a->pics[i].iPOC;
+			a->iPictInfoIndex = i;
+			firstvalid = i;
+			break;
+		}
+	}
+
+	for(i = 0; i <= a->iLargestBufferedPicIndex; i++){
+		if(i == firstvalid)
+			continue;
+		if(a->pics[i].iPOC > IMinInt32 && a->pics[i].iPOC < a->iMinPOC){
+			a->iMinPOC = a->pics[i].iPOC;
+			a->iPictInfoIndex = i;
+		}
+	}
+
+	if(a->iMinPOC > IMinInt32){
+		a->iLastWrittenPOC = a->iMinPOC;
+		memmove(&a->info, &a->pics[a->iPictInfoIndex].sBufferInfo, sizeof(a->info));
+		a->data[0] = a->info.pDst[0];
+		a->data[1] = a->info.pDst[1];
+		a->data[2] = a->info.pDst[2];
+		a->pics[a->iPictInfoIndex].iPOC = IMinInt32;
+		a->ctx.pPicBuff->ppPic[a->pics[a->iPictInfoIndex].iPicBuffIdx]->iRefCount--;
+		a->pics[a->iPictInfoIndex].bLastGOP = false;
+		a->iMinPOC = IMinInt32;
+		a->iNumOfPicts--;
+	}
+}
+
+int
+h264decode(H264Aux *a, u8int *buf, int sz, uvlong *timestamp)
+{
+	int res;
+
+	if(buf == nil || sz < 1){
+		a->ctx.bEndOfStreamFlag = true;
+		a->ctx.bInstantDecFlag = true;
+	}else{
+		a->ctx.bEndOfStreamFlag = false;
+	}
+	memset(a->data, 0, sizeof(a->data));
+	memset(&a->info, 0, sizeof(a->info));
+	a->info.uiInBsTimeStamp = *timestamp;
+	a->ctx.uiTimeStamp = *timestamp;
+	a->ctx.iErrorCode = dsErrorFree;
+	a->ctx.iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL;
+	a->ctx.bReferenceLostAtT0Flag = false;
+	a->ctx.bCurAuContainLtrMarkSeFlag = false;
+	a->ctx.iFrameNumOfAuMarkedLtr = 0;
+	a->ctx.iFrameNum = -1;
+	a->ctx.iFeedbackTidInAu = -1;
+	a->ctx.iFeedbackNalRefIdc = -1;
+	res = WelsDecodeBs(&a->ctx, buf, sz, a->data, &a->info, nil);
+	a->ctx.bInstantDecFlag = false;
+	if(res != 0){
+		if(res & dsOutOfMemory)
+			return 0;
+		werrstr("%s: %.*H", h264err2s(a->ctx.iErrorCode), sz <= 32 ? sz : 32, buf);
+		return -1;
+	}
+
+	if(a->info.iBufferStatus != 0 && a->ctx.pPps->bEntropyCodingModeFlag && a->ctx.pSps->uiProfileIdc != 66 && a->ctx.pSps->uiProfileIdc != 83){
+		/* non-baseline needs reordering */
+		reorder(a);
+		*timestamp = a->info.uiOutYuvTimeStamp;
+	}
+
+	return 0;
+}
+
+char *
+h264err2s(int err)
+{
+	static char t[256];
+	char *s, *e;
+
+	t[0] = t[1] = 0;
+	s = t;
+	e = t+sizeof(t);
+	if(err & dsFramePending)       s = seprint(s, e, "|FramePending");
+	if(err & dsRefLost)            s = seprint(s, e, "|RefLost");
+	if(err & dsBitstreamError)     s = seprint(s, e, "|BitstreamError");
+	if(err & dsDepLayerLost)       s = seprint(s, e, "|DepLayerLost");
+	if(err & dsNoParamSets)        s = seprint(s, e, "|NoParamSets");
+	if(err & dsDataErrorConcealed) s = seprint(s, e, "|DataErrorConcealed");
+	if(err & dsRefListNullPtrs)    s = seprint(s, e, "|RefListNullPtrs");
+	if(err & dsInvalidArgument)    s = seprint(s, e, "|InvalidArgument");
+	if(err & dsInitialOptExpected) s = seprint(s, e, "|InitialOptExpected");
+	if(err & dsOutOfMemory)        s = seprint(s, e, "|OutOfMemory");
+	if(err & dsDstBufNeedExpan)    s = seprint(s, e, "|DstBufNeedExpan");
+	USED(s);
+
+	return t+1;
+}
 
 uint32_t
 WelsCPUFeatureDetect(int32_t *pNumberOfLogicProcessors)