#include "decoder.h"#include "decoder9.h" static voidreorder(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--; }} voidh264flush(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--; }} inth264decode(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_tWelsCPUFeatureDetect(int32_t *pNumberOfLogicProcessors){ char *s; s = getenv("NPROC"); *pNumberOfLogicProcessors = s ? atoi(s) : 0; return 0;} voidEventPost(SWelsDecEvent* e){ USED(e);} intEventCreate(SWelsDecEvent *e, int manualReset, int initialState){ USED(e, manualReset, initialState); return 0;} intEventWait(SWelsDecEvent *e, int32_t timeout){ USED(e, timeout); return 0;} voidEventDestroy(SWelsDecEvent *e){ USED(e);} voidEventReset(SWelsDecEvent *e){ USED(e);} void *WelsMallocz(const uint32_t kuiSize, const char *kpTag){ void *p; USED(kpTag); if((p = mallocalign(kuiSize, 16, 0, 0)) == nil) return nil; return memset(p, 0, kuiSize);} static void *WelsMalloc(const uint32_t kuiSize, const char *kpTag){ USED(kpTag); return mallocalign(kuiSize, 16, 0, 0);} voidWelsFree(void *pPointer, const char *kpTag){ USED(kpTag); free(pPointer);} static uint32_tWelsGetCacheLineSize(void){ return 16;} static uint32_tWelsGetMemoryUsage(void){ return 0;} CMemoryAlign cMemoryAlign = {#ifdef MEMORY_MONITOR .m_nMemoryUsageInBytes = 0,#endif .m_nCacheLineSize = 16, .WelsMallocz = WelsMallocz, .WelsMalloc = WelsMalloc, .WelsFree = WelsFree, .WelsGetCacheLineSize = WelsGetCacheLineSize, .WelsGetMemoryUsage = WelsGetMemoryUsage,};
#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)
{
char *s;
s = getenv("NPROC");
*pNumberOfLogicProcessors = s ? atoi(s) : 0;
return 0;
}
void
EventPost(SWelsDecEvent* e)
{
USED(e);
}
int
EventCreate(SWelsDecEvent *e, int manualReset, int initialState)
{
USED(e, manualReset, initialState);
return 0;
}
int
EventWait(SWelsDecEvent *e, int32_t timeout)
{
USED(e, timeout);
return 0;
}
void
EventDestroy(SWelsDecEvent *e)
{
USED(e);
}
void
EventReset(SWelsDecEvent *e)
{
USED(e);
}
void *
WelsMallocz(const uint32_t kuiSize, const char *kpTag)
{
void *p;
USED(kpTag);
if((p = mallocalign(kuiSize, 16, 0, 0)) == nil)
return nil;
return memset(p, 0, kuiSize);
}
static void *
WelsMalloc(const uint32_t kuiSize, const char *kpTag)
{
USED(kpTag);
return mallocalign(kuiSize, 16, 0, 0);
}
void
WelsFree(void *pPointer, const char *kpTag)
{
USED(kpTag);
free(pPointer);
}
static uint32_t
WelsGetCacheLineSize(void)
{
return 16;
}
static uint32_t
WelsGetMemoryUsage(void)
{
return 0;
}
CMemoryAlign cMemoryAlign = {
#ifdef MEMORY_MONITOR
.m_nMemoryUsageInBytes = 0,
#endif
.m_nCacheLineSize = 16,
.WelsMallocz = WelsMallocz,
.WelsMalloc = WelsMalloc,
.WelsFree = WelsFree,
.WelsGetCacheLineSize = WelsGetCacheLineSize,
.WelsGetMemoryUsage = WelsGetMemoryUsage,
};