~ft/openh264

a31395562e9757b7d7fa12bb87b6cc6a3d495a93 — Sigrid Solveig Haflínudóttir 1 year, 11 months ago 55b3ec0
add 9-specific decoder logic
1 files changed, 216 insertions(+), 0 deletions(-)

M codec/plan9.c
M codec/plan9.c => codec/plan9.c +216 -0
@@ 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)