-e90961, fix aac+vqe "reamain data not process AEC" bug. -3c08de, split module vpu into vi vo vpss rgn gdc. -b5d998, (ive): add comment to api. -166849, mw support arm32. Change-Id: Ied488d392da9eed2e3a94e1244eeee540c389372
826 lines
25 KiB
C
826 lines
25 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
#include <poll.h>
|
|
#include <sys/time.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/prctl.h>
|
|
#include <inttypes.h>
|
|
#include "sample_comm.h"
|
|
|
|
VB_SOURCE_E g_enVdecVBSource = VB_SOURCE_MODULE;
|
|
|
|
VB_POOL g_ahPicVbPool[VDEC_MAX_CHN_NUM] = { [0 ...(VDEC_MAX_CHN_NUM - 1)] = VB_INVALID_POOLID };
|
|
VB_POOL g_ahTmvVbPool[VDEC_MAX_CHN_NUM] = { [0 ...(VDEC_MAX_CHN_NUM - 1)] = VB_INVALID_POOLID };
|
|
|
|
static inline CVI_VOID PRINTF_VDEC_CHN_STATUS(CVI_S32 Chn, VDEC_CHN_STATUS_S stStatus)
|
|
{
|
|
CVI_VDEC_PRNT("\033[0;33m ---------------------------------------");
|
|
CVI_VDEC_PRNT("------------------------------------------------------------\033[0;39m\n");
|
|
CVI_VDEC_PRNT("\033[0;33m chn:%d, Type:%d, bStart:%d, DecodeFrames:%d, LeftPics:%d,",
|
|
Chn, stStatus.enType, stStatus.bStartRecvStream, stStatus.u32DecodeStreamFrames, stStatus.u32LeftPics);
|
|
CVI_VDEC_PRNT("LeftBytes:%d, LeftFrames:%d, RecvFrames:%d \033[0;39m\n",
|
|
stStatus.u32LeftStreamBytes, stStatus.u32LeftStreamFrames, stStatus.u32RecvStreamFrames);
|
|
CVI_VDEC_PRNT("\033[0;33m FormatErr:%d, s32PicSizeErrSet:%d, s32StreamUnsprt:%d,",
|
|
stStatus.stVdecDecErr.s32FormatErr, stStatus.stVdecDecErr.s32PicSizeErrSet,
|
|
stStatus.stVdecDecErr.s32StreamUnsprt);
|
|
CVI_VDEC_PRNT("s32PackErr:%d, u32PrtclNumErrSet:%d, s32RefErrSet:%d, s32PicBufSizeErrSet:%d \033[0;39m\n",
|
|
stStatus.stVdecDecErr.s32PackErr, stStatus.stVdecDecErr.s32PrtclNumErrSet,
|
|
stStatus.stVdecDecErr.s32RefErrSet, stStatus.stVdecDecErr.s32PicBufSizeErrSet);
|
|
CVI_VDEC_PRNT("\033[0;33m ----------------------------------------");
|
|
CVI_VDEC_PRNT("-----------------------------------------------------------\033[0;39m\n");
|
|
}
|
|
|
|
|
|
static inline CVI_S32 SAVE_FILE_NAME(CVI_CHAR *aFileName, CVI_S32 chn, CVI_CHAR *cStreamName,
|
|
PIXEL_FORMAT_E enPixelFormat)
|
|
{
|
|
CVI_CHAR *Postfix;
|
|
|
|
if (enPixelFormat == PIXEL_FORMAT_RGB_888) {
|
|
Postfix = "rgb888";
|
|
} else if (enPixelFormat == PIXEL_FORMAT_BGR_888) {
|
|
Postfix = "bgr888";
|
|
} else if (enPixelFormat == PIXEL_FORMAT_ARGB_8888) {
|
|
Postfix = "argb8888";
|
|
} else if (enPixelFormat == PIXEL_FORMAT_ARGB_1555) {
|
|
Postfix = "argb1555";
|
|
} else if (enPixelFormat == PIXEL_FORMAT_YUV_400 ||
|
|
enPixelFormat == PIXEL_FORMAT_YUV_PLANAR_420 ||
|
|
enPixelFormat == PIXEL_FORMAT_YUV_PLANAR_422 ||
|
|
enPixelFormat == PIXEL_FORMAT_YUV_PLANAR_444 ||
|
|
enPixelFormat == PIXEL_FORMAT_NV12 ||
|
|
enPixelFormat == PIXEL_FORMAT_NV21) {
|
|
Postfix = "yuv";
|
|
} else {
|
|
CVI_VDEC_ERR("[%s]-%d: enPixelFormat type err", __func__, __LINE__);
|
|
Postfix = "unk";
|
|
}
|
|
CVI_VDEC_INFO("aFileName = %s, cStreamName = %s\n", aFileName, cStreamName);
|
|
sprintf(aFileName, "chn%d_%s.%s", chn, cStreamName, Postfix);
|
|
CVI_VDEC_INFO("aFileName = %s\n", aFileName);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void get_chroma_size_shift_factor(PIXEL_FORMAT_E enPixelFormat, CVI_S32 *w_shift, CVI_S32 *h_shift)
|
|
{
|
|
switch (enPixelFormat) {
|
|
case PIXEL_FORMAT_YUV_PLANAR_420:
|
|
*w_shift = 1;
|
|
*h_shift = 1;
|
|
break;
|
|
case PIXEL_FORMAT_YUV_PLANAR_422:
|
|
*w_shift = 1;
|
|
*h_shift = 0;
|
|
break;
|
|
case PIXEL_FORMAT_YUV_PLANAR_444:
|
|
*w_shift = 0;
|
|
*h_shift = 0;
|
|
break;
|
|
case PIXEL_FORMAT_NV12:
|
|
case PIXEL_FORMAT_NV21:
|
|
*w_shift = 0;
|
|
*h_shift = 1;
|
|
break;
|
|
case PIXEL_FORMAT_YUV_400: // no chroma
|
|
default:
|
|
*w_shift = 31;
|
|
*h_shift = 31;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int write_yuv(FILE *out_f, VIDEO_FRAME_S stVFrame)
|
|
{
|
|
CVI_S32 c_w_shift, c_h_shift; // chroma width/height shift
|
|
CVI_U8 *w_ptr;
|
|
|
|
CVI_VDEC_INFO("u32Width = %d, u32Height = %d\n",
|
|
stVFrame.u32Width, stVFrame.u32Height);
|
|
CVI_VDEC_INFO("u32Stride[0] = %d, u32Stride[1] = %d, u32Stride[2] = %d\n",
|
|
stVFrame.u32Stride[0], stVFrame.u32Stride[1], stVFrame.u32Stride[2]);
|
|
CVI_VDEC_INFO("u32Length[0] = %d, u32Length[1] = %d, u32Length[2] = %d\n",
|
|
stVFrame.u32Length[0], stVFrame.u32Length[1], stVFrame.u32Length[2]);
|
|
|
|
get_chroma_size_shift_factor(stVFrame.enPixelFormat, &c_w_shift, &c_h_shift);
|
|
|
|
w_ptr = stVFrame.pu8VirAddr[0];
|
|
for (CVI_U32 i = 0; i < stVFrame.u32Height; i++) {
|
|
fwrite(w_ptr + i * stVFrame.u32Stride[0], 1, stVFrame.u32Width, out_f);
|
|
}
|
|
|
|
if (stVFrame.pu8VirAddr[1]) {
|
|
w_ptr = stVFrame.pu8VirAddr[1];
|
|
for (CVI_U32 i = 0; i < (stVFrame.u32Height >> c_h_shift); i++) {
|
|
fwrite(w_ptr + i * stVFrame.u32Stride[1], 1, stVFrame.u32Width >> c_w_shift, out_f);
|
|
}
|
|
}
|
|
|
|
if (stVFrame.pu8VirAddr[2]) {
|
|
w_ptr = stVFrame.pu8VirAddr[2];
|
|
for (CVI_U32 i = 0; i < (stVFrame.u32Height >> c_h_shift); i++) {
|
|
fwrite(w_ptr + i * stVFrame.u32Stride[2], 1, stVFrame.u32Width >> c_w_shift, out_f);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int md5Sum_update(MD5_CTX *ptMD5Ctx, VIDEO_FRAME_S stVFrame)
|
|
{
|
|
CVI_S32 c_w_shift, c_h_shift; // chroma width/height shift
|
|
CVI_U8 *w_ptr;
|
|
|
|
CVI_VDEC_INFO("u32Width = %d, u32Height = %d\n",
|
|
stVFrame.u32Width, stVFrame.u32Height);
|
|
CVI_VDEC_INFO("u32Stride[0] = %d, u32Stride[1] = %d, u32Stride[2] = %d\n",
|
|
stVFrame.u32Stride[0], stVFrame.u32Stride[1], stVFrame.u32Stride[2]);
|
|
CVI_VDEC_INFO("u32Length[0] = %d, u32Length[1] = %d, u32Length[2] = %d\n",
|
|
stVFrame.u32Length[0], stVFrame.u32Length[1], stVFrame.u32Length[2]);
|
|
|
|
get_chroma_size_shift_factor(stVFrame.enPixelFormat, &c_w_shift, &c_h_shift);
|
|
|
|
w_ptr = stVFrame.pu8VirAddr[0];
|
|
for (CVI_U32 i = 0; i < stVFrame.u32Height; i++) {
|
|
MD5_Update(ptMD5Ctx, w_ptr + i * stVFrame.u32Stride[0], stVFrame.u32Width);
|
|
}
|
|
usleep(1000);
|
|
if (stVFrame.pu8VirAddr[1]) {
|
|
w_ptr = stVFrame.pu8VirAddr[1];
|
|
for (CVI_U32 i = 0; i < (stVFrame.u32Height >> c_h_shift); i++) {
|
|
MD5_Update(ptMD5Ctx, w_ptr + i * stVFrame.u32Stride[1], stVFrame.u32Width >> c_w_shift);
|
|
}
|
|
}
|
|
usleep(1000);
|
|
if (stVFrame.pu8VirAddr[2]) {
|
|
w_ptr = stVFrame.pu8VirAddr[2];
|
|
for (CVI_U32 i = 0; i < (stVFrame.u32Height >> c_h_shift); i++) {
|
|
MD5_Update(ptMD5Ctx, w_ptr + i * stVFrame.u32Stride[2], stVFrame.u32Width >> c_w_shift);
|
|
}
|
|
}
|
|
usleep(1000);
|
|
return 0;
|
|
}
|
|
|
|
//VB_SOURCE_E g_VdecVbSrc = VB_SOURCE_PRIVATE;
|
|
//VB_SOURCE_E g_VdecVbSrc = VB_SOURCE_USER;
|
|
VB_SOURCE_E g_VdecVbSrc = VB_SOURCE_COMMON;
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_SetVBPool(CVI_S32 Chn, CVI_U32 VBPoolID)
|
|
{
|
|
if (Chn >= VDEC_MAX_CHN_NUM) {
|
|
CVI_VDEC_ERR("SAMPLE_COMM_VDEC_SetVBPool Fail\n");
|
|
return CVI_FAILURE;
|
|
}
|
|
g_ahPicVbPool[Chn] = VBPoolID;
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_GetVBPool(CVI_S32 Chn)
|
|
{
|
|
if (Chn >= VDEC_MAX_CHN_NUM) {
|
|
CVI_VDEC_ERR("SAMPLE_COMM_VDEC_GetVBPool Fail\n");
|
|
return CVI_FAILURE;
|
|
}
|
|
return g_ahPicVbPool[Chn];
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_InitVBPool(VDEC_CHN ChnNum, SAMPLE_VDEC_ATTR *pastSampleVdec)
|
|
{
|
|
CVI_S32 s32Ret = CVI_SUCCESS, i;
|
|
SAMPLE_VDEC_BUF astSampleVdecBuf[VDEC_MAX_CHN_NUM];
|
|
VB_POOL_CONFIG_S stVbPoolCfg;
|
|
|
|
if (g_VdecVbSrc != VB_SOURCE_USER)
|
|
return s32Ret;
|
|
|
|
for (i = 0; i < ChnNum; i++) {
|
|
if (pastSampleVdec[i].enType == PT_JPEG ||
|
|
pastSampleVdec[i].enType == PT_MJPEG) {
|
|
astSampleVdecBuf[i].u32PicBufSize = 0;
|
|
} else {
|
|
astSampleVdecBuf[i].u32PicBufSize =
|
|
VDEC_GetPicBufferSize(pastSampleVdec[i].enType,
|
|
pastSampleVdec[i].u32Width,
|
|
pastSampleVdec[i].u32Height,
|
|
pastSampleVdec[i].enPixelFormat,
|
|
DATA_BITWIDTH_8,
|
|
COMPRESS_MODE_NONE);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ChnNum; i++) {
|
|
if ((astSampleVdecBuf[i].u32PicBufSize != 0) && (pastSampleVdec[i].u32FrameBufCnt != 0)) {
|
|
memset(&stVbPoolCfg, 0, sizeof(VB_POOL_CONFIG_S));
|
|
stVbPoolCfg.u32BlkSize = astSampleVdecBuf[i].u32PicBufSize;
|
|
stVbPoolCfg.u32BlkCnt = pastSampleVdec[i].u32FrameBufCnt;
|
|
stVbPoolCfg.enRemapMode = VB_REMAP_MODE_NONE;
|
|
|
|
g_ahPicVbPool[i] = CVI_VB_CreatePool(&stVbPoolCfg);
|
|
CVI_VDEC_TRACE("CVI_VB_CreatePool : %d, u32BlkSize=0x%x, u32BlkCnt=%d\n",
|
|
g_ahPicVbPool[i], stVbPoolCfg.u32BlkSize, stVbPoolCfg.u32BlkCnt);
|
|
|
|
if (g_ahPicVbPool[i] == VB_INVALID_POOLID) {
|
|
CVI_VDEC_ERR("CVI_VB_CreatePool Fail\n");
|
|
return CVI_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return s32Ret;
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_ExitVBPool(CVI_VOID)
|
|
{
|
|
CVI_S32 i, m, s32Ret;
|
|
|
|
if (g_VdecVbSrc != VB_SOURCE_USER)
|
|
return;
|
|
|
|
for (i = 0; i < VDEC_MAX_CHN_NUM; i++) {
|
|
if (g_ahPicVbPool[i] != VB_INVALID_POOLID) {
|
|
CVI_VDEC_TRACE("g_ahPicVbPool[Chn%d]CVI_VB_DestroyPool : %d\n", i, g_ahPicVbPool[i]);
|
|
|
|
s32Ret = CVI_VB_DestroyPool(g_ahPicVbPool[i]);
|
|
if (s32Ret != CVI_SUCCESS) {
|
|
CVI_VDEC_ERR("g_ahPicVbPool[Chn%d]CVI_VB_DestroyPool : %d fail!\n",
|
|
i, g_ahPicVbPool[i]);
|
|
}
|
|
for (m = i + 1; m < VDEC_MAX_CHN_NUM; m++)
|
|
if (g_ahPicVbPool[m] == g_ahPicVbPool[i])
|
|
g_ahPicVbPool[m] = VB_INVALID_POOLID;
|
|
g_ahPicVbPool[i] = VB_INVALID_POOLID;
|
|
}
|
|
|
|
if (g_ahTmvVbPool[i] != VB_INVALID_POOLID) {
|
|
CVI_VDEC_TRACE("g_ahTmvVbPool[Chn%d]CVI_VB_DestroyPool : %d\n", i, g_ahTmvVbPool[i]);
|
|
|
|
s32Ret = CVI_VB_DestroyPool(g_ahTmvVbPool[i]);
|
|
if (s32Ret != CVI_SUCCESS) {
|
|
CVI_VDEC_ERR("g_ahTmvVbPool[Chn%d]CVI_VB_DestroyPool : %d fail!\n",
|
|
i, g_ahTmvVbPool[i]);
|
|
}
|
|
for (m = i + 1; m < VDEC_MAX_CHN_NUM; m++)
|
|
if (g_ahTmvVbPool[m] == g_ahTmvVbPool[i])
|
|
g_ahTmvVbPool[m] = VB_INVALID_POOLID;
|
|
g_ahTmvVbPool[i] = VB_INVALID_POOLID;
|
|
}
|
|
}
|
|
}
|
|
|
|
CVI_VOID *SAMPLE_COMM_VDEC_SendStream(CVI_VOID *pArgs)
|
|
{
|
|
VDEC_THREAD_PARAM_S *pstVdecThreadParam = (VDEC_THREAD_PARAM_S *)pArgs;
|
|
CVI_BOOL bEndOfStream = CVI_FALSE;
|
|
CVI_S32 s32UsedBytes = 0, s32ReadLen = 0;
|
|
FILE *fpStrm = NULL;
|
|
CVI_U8 *pu8Buf = NULL;
|
|
VDEC_STREAM_S stStream;
|
|
CVI_BOOL bFindStart, bFindEnd;
|
|
CVI_U64 u64PTS = 0;
|
|
CVI_U32 u32Len, u32Start;
|
|
CVI_S32 s32Ret, i;
|
|
CVI_CHAR cStreamFile[256];
|
|
|
|
CVI_VDEC_TRACE("\n");
|
|
|
|
prctl(PR_SET_NAME, "VideoSendStream", 0, 0, 0);
|
|
|
|
snprintf(cStreamFile, sizeof(cStreamFile), "%s", pstVdecThreadParam->cFileName);
|
|
if (cStreamFile != 0) {
|
|
fpStrm = fopen(cStreamFile, "rb");
|
|
CVI_VDEC_INFO("cStreamFile = %s\n", cStreamFile);
|
|
|
|
if (fpStrm == NULL) {
|
|
CVI_VDEC_ERR("chn %d can't open file %s in send stream thread!\n",
|
|
pstVdecThreadParam->s32ChnId, cStreamFile);
|
|
pstVdecThreadParam->bFileEnd = CVI_TRUE;
|
|
return (CVI_VOID *)(CVI_FAILURE);
|
|
}
|
|
}
|
|
|
|
CVI_VDEC_TRACE("\n \033[0;36m chn %d, stream file:%s, userbufsize: %d \033[0;39m\n",
|
|
pstVdecThreadParam->s32ChnId,
|
|
pstVdecThreadParam->cFileName,
|
|
pstVdecThreadParam->s32MinBufSize);
|
|
|
|
pu8Buf = malloc(pstVdecThreadParam->s32MinBufSize);
|
|
if (pu8Buf == NULL) {
|
|
CVI_VDEC_ERR("chn %d can't alloc %d in send stream thread!\n",
|
|
pstVdecThreadParam->s32ChnId,
|
|
pstVdecThreadParam->s32MinBufSize);
|
|
fclose(fpStrm);
|
|
pstVdecThreadParam->bFileEnd = CVI_TRUE;
|
|
return (CVI_VOID *)(CVI_FAILURE);
|
|
}
|
|
fflush(stdout);
|
|
|
|
u64PTS = pstVdecThreadParam->u64PtsInit;
|
|
while (1) {
|
|
if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_STOP) {
|
|
CVI_VDEC_TRACE("eThreadCtrl = THREAD_CTRL_STOP\n");
|
|
break;
|
|
} else if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_PAUSE) {
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
bEndOfStream = CVI_FALSE;
|
|
bFindStart = CVI_FALSE;
|
|
bFindEnd = CVI_FALSE;
|
|
u32Start = 0;
|
|
s32Ret = fseek(fpStrm, s32UsedBytes, SEEK_SET);
|
|
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
|
|
if (s32ReadLen == 0) {
|
|
if (pstVdecThreadParam->bCircleSend == CVI_TRUE) {
|
|
memset(&stStream, 0, sizeof(VDEC_STREAM_S));
|
|
stStream.bEndOfStream = CVI_TRUE;
|
|
SendAgainFlag:
|
|
s32Ret = CVI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);
|
|
if (s32Ret == CVI_ERR_VDEC_BUSY) {
|
|
CVI_VDEC_TRACE("timeout in vdec sendstream\n");
|
|
goto SendAgainFlag;
|
|
}
|
|
|
|
s32UsedBytes = 0;
|
|
fseek(fpStrm, 0, SEEK_SET);
|
|
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
|
|
} else {
|
|
CVI_VDEC_TRACE("break\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pstVdecThreadParam->s32StreamMode == VIDEO_MODE_FRAME &&
|
|
pstVdecThreadParam->enType == PT_H264) {
|
|
for (i = 0; i < s32ReadLen - 8; i++) {
|
|
int tmp = pu8Buf[i + 3] & 0x1F;
|
|
|
|
if (pu8Buf[i] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
|
|
(((tmp == 0x5 || tmp == 0x1) && ((pu8Buf[i + 4] & 0x80) == 0x80)) ||
|
|
(tmp == 20 && (pu8Buf[i + 7] & 0x80) == 0x80))) {
|
|
bFindStart = CVI_TRUE;
|
|
i += 8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i < s32ReadLen - 8; i++) {
|
|
int tmp = pu8Buf[i + 3] & 0x1F;
|
|
|
|
if (pu8Buf[i] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
|
|
(tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 ||
|
|
((tmp == 5 || tmp == 1) && ((pu8Buf[i + 4] & 0x80) == 0x80)) ||
|
|
(tmp == 20 && (pu8Buf[i + 7] & 0x80) == 0x80))) {
|
|
bFindEnd = CVI_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i > 0)
|
|
s32ReadLen = i;
|
|
if (bFindStart == CVI_FALSE) {
|
|
CVI_VDEC_TRACE("chn %d can not find H264 start code!s32ReadLen %d, s32UsedBytes %d.!\n",
|
|
pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
|
|
}
|
|
if (bFindEnd == CVI_FALSE) {
|
|
s32ReadLen = i + 8;
|
|
}
|
|
|
|
} else if (pstVdecThreadParam->s32StreamMode == VIDEO_MODE_FRAME &&
|
|
pstVdecThreadParam->enType == PT_H265) {
|
|
CVI_BOOL bNewPic = CVI_FALSE;
|
|
|
|
for (i = 0; i < s32ReadLen - 6; i++) {
|
|
CVI_U32 tmp = (pu8Buf[i + 3] & 0x7E) >> 1;
|
|
|
|
bNewPic = (pu8Buf[i + 0] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
|
|
(tmp <= 21) && ((pu8Buf[i + 5] & 0x80) == 0x80));
|
|
|
|
if (bNewPic) {
|
|
bFindStart = CVI_TRUE;
|
|
i += 6;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i < s32ReadLen - 6; i++) {
|
|
CVI_U32 tmp = (pu8Buf[i + 3] & 0x7E) >> 1;
|
|
|
|
bNewPic = (pu8Buf[i + 0] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 &&
|
|
(tmp == 32 || tmp == 33 || tmp == 34 || tmp == 39 || tmp == 40 ||
|
|
((tmp <= 21) && (pu8Buf[i + 5] & 0x80) == 0x80)));
|
|
|
|
if (bNewPic) {
|
|
bFindEnd = CVI_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (i > 0)
|
|
s32ReadLen = i;
|
|
|
|
if (bFindStart == CVI_FALSE) {
|
|
CVI_VDEC_TRACE("chn %d can not find H265 start code!s32ReadLen %d, s32UsedBytes %d.!\n",
|
|
pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
|
|
}
|
|
if (bFindEnd == CVI_FALSE) {
|
|
s32ReadLen = i + 6;
|
|
}
|
|
|
|
} else if (pstVdecThreadParam->enType == PT_MJPEG || pstVdecThreadParam->enType == PT_JPEG) {
|
|
for (i = 0; i < s32ReadLen - 1; i++) {
|
|
if (pu8Buf[i] == 0xFF && pu8Buf[i + 1] == 0xD8) {
|
|
u32Start = i;
|
|
bFindStart = CVI_TRUE;
|
|
i = i + 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i < s32ReadLen - 3; i++) {
|
|
if ((pu8Buf[i] == 0xFF) && (pu8Buf[i + 1] & 0xF0) == 0xE0) {
|
|
u32Len = (pu8Buf[i + 2] << 8) + pu8Buf[i + 3];
|
|
i += 1 + u32Len;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i < s32ReadLen - 1; i++) {
|
|
if (pu8Buf[i] == 0xFF && pu8Buf[i + 1] == 0xD9) {
|
|
bFindEnd = CVI_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
s32ReadLen = i + 2;
|
|
|
|
if (bFindStart == CVI_FALSE) {
|
|
CVI_VDEC_TRACE("chn %d can not find JPEG start code!s32ReadLen %d, s32UsedBytes %d.!\n",
|
|
pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
|
|
}
|
|
} else {
|
|
if ((s32ReadLen != 0) && (s32ReadLen < pstVdecThreadParam->s32MinBufSize)) {
|
|
bEndOfStream = CVI_TRUE;
|
|
}
|
|
}
|
|
|
|
stStream.u64PTS = u64PTS;
|
|
stStream.pu8Addr = pu8Buf + u32Start;
|
|
stStream.u32Len = s32ReadLen;
|
|
stStream.bEndOfFrame = (pstVdecThreadParam->s32StreamMode == VIDEO_MODE_FRAME) ? CVI_TRUE : CVI_FALSE;
|
|
stStream.bEndOfStream = bEndOfStream;
|
|
stStream.bDisplay = 1;
|
|
|
|
SendAgain:
|
|
s32Ret = CVI_VDEC_SendStream(pstVdecThreadParam->s32ChnId,
|
|
&stStream, pstVdecThreadParam->s32MilliSec);
|
|
if ((s32Ret != CVI_SUCCESS) &&
|
|
(pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_START)) {
|
|
usleep(pstVdecThreadParam->s32IntervalTime);
|
|
|
|
if (s32Ret == CVI_ERR_VDEC_BUSY)
|
|
CVI_VDEC_TRACE("timeout in vdec sendstream\n");
|
|
|
|
goto SendAgain;
|
|
} else {
|
|
bEndOfStream = CVI_FALSE;
|
|
s32UsedBytes = s32UsedBytes + s32ReadLen + u32Start;
|
|
u64PTS += pstVdecThreadParam->u64PtsIncrease;
|
|
}
|
|
usleep(pstVdecThreadParam->s32IntervalTime);
|
|
}
|
|
|
|
/* send the flag of stream end */
|
|
memset(&stStream, 0, sizeof(VDEC_STREAM_S));
|
|
stStream.bEndOfStream = CVI_TRUE;
|
|
CVI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);
|
|
|
|
CVI_VDEC_TRACE("\033[0;35m chn %d send steam thread return ... \033[0;39m\n",
|
|
pstVdecThreadParam->s32ChnId);
|
|
|
|
pstVdecThreadParam->bFileEnd = CVI_TRUE;
|
|
CVI_VDEC_TRACE("File end in chn[%d]\n", pstVdecThreadParam->s32ChnId);
|
|
|
|
fflush(stdout);
|
|
if (pu8Buf != CVI_NULL) {
|
|
free(pu8Buf);
|
|
}
|
|
fclose(fpStrm);
|
|
|
|
return (CVI_VOID *)CVI_SUCCESS;
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_CmdCtrl(VDEC_THREAD_PARAM_S *pstVdecSend, pthread_t *pVdecThread)
|
|
{
|
|
CVI_S32 s32Ret;
|
|
VDEC_CHN_STATUS_S stStatus;
|
|
char c = 0;
|
|
|
|
if (pstVdecSend->bCircleSend == CVI_TRUE) {
|
|
goto WHILE;
|
|
}
|
|
|
|
CVI_VDEC_TRACE("decoding..............\n");
|
|
|
|
if (*pVdecThread != 0) {
|
|
s32Ret = pthread_join(*pVdecThread, CVI_NULL);
|
|
if (s32Ret == 0) {
|
|
*pVdecThread = 0;
|
|
}
|
|
}
|
|
*pVdecThread = 0;
|
|
|
|
while (1) {
|
|
s32Ret = CVI_VDEC_QueryStatus(pstVdecSend->s32ChnId, &stStatus);
|
|
if (s32Ret != CVI_SUCCESS) {
|
|
CVI_VDEC_WARN("chn %d CVI_MPI_VDEC_QueryStatus fail!!!\n", s32Ret);
|
|
return;
|
|
}
|
|
if ((stStatus.u32LeftStreamBytes == 0) && (stStatus.u32LeftPics == 0) &&
|
|
(pstVdecSend->bFileEnd == CVI_TRUE)) {
|
|
PRINTF_VDEC_CHN_STATUS(pstVdecSend->s32ChnId, stStatus);
|
|
break;
|
|
}
|
|
usleep(1000);
|
|
}
|
|
|
|
CVI_VDEC_TRACE("end!\n");
|
|
return;
|
|
|
|
WHILE:
|
|
while (1) {
|
|
printf("\nSAMPLE_TEST:press 'e' to exit; 'q' to query;\n");
|
|
c = getchar();
|
|
|
|
if (c == 'e')
|
|
break;
|
|
else if (c == 'q') {
|
|
CVI_VDEC_QueryStatus(pstVdecSend->s32ChnId, &stStatus);
|
|
PRINTF_VDEC_CHN_STATUS(pstVdecSend->s32ChnId, stStatus);
|
|
}
|
|
}
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_StartSendStream(VDEC_THREAD_PARAM_S *pstVdecSend,
|
|
pthread_t *pVdecThread)
|
|
{
|
|
struct sched_param param;
|
|
pthread_attr_t attr;
|
|
|
|
param.sched_priority = 80;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
pthread_create(pVdecThread, &attr, SAMPLE_COMM_VDEC_SendStream, (CVI_VOID *)pstVdecSend);
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_StopSendStream(VDEC_THREAD_PARAM_S *pstVdecSend, pthread_t *pVdecThread)
|
|
{
|
|
pstVdecSend->eThreadCtrl = THREAD_CTRL_STOP;
|
|
if (*pVdecThread != 0) {
|
|
pthread_join(*pVdecThread, CVI_NULL);
|
|
*pVdecThread = 0;
|
|
}
|
|
}
|
|
|
|
CVI_VOID *SAMPLE_COMM_VDEC_GetPic(CVI_VOID *pArgs)
|
|
{
|
|
VDEC_THREAD_PARAM_S *pstVdecThreadParam = (VDEC_THREAD_PARAM_S *)pArgs;
|
|
FILE *fp = CVI_NULL;
|
|
CVI_S32 s32Ret, s32Cnt = 0;
|
|
VDEC_CHN_ATTR_S stAttr;
|
|
VIDEO_FRAME_INFO_S stVFrame;
|
|
VIDEO_FRAME_S *pstVFrame = &stVFrame.stVFrame;
|
|
CVI_CHAR cSaveFile[256];
|
|
|
|
CVI_VDEC_TRACE("\n");
|
|
|
|
prctl(PR_SET_NAME, "VdecGetPic", 0, 0, 0);
|
|
|
|
s32Ret = CVI_VDEC_GetChnAttr(pstVdecThreadParam->s32ChnId, &stAttr);
|
|
if (s32Ret != CVI_SUCCESS) {
|
|
CVI_VDEC_ERR("chn %d get chn attr fail for %#x!\n",
|
|
pstVdecThreadParam->s32ChnId,
|
|
s32Ret);
|
|
return (CVI_VOID *)(CVI_FAILURE);
|
|
}
|
|
|
|
if (stAttr.enType != PT_JPEG &&
|
|
stAttr.enType != PT_H264 &&
|
|
stAttr.enType != PT_H265 &&
|
|
stAttr.enType != PT_MJPEG) {
|
|
CVI_VDEC_ERR("chn %d enType %d do not support save file!\n",
|
|
pstVdecThreadParam->s32ChnId,
|
|
stAttr.enType);
|
|
return (CVI_VOID *)(CVI_FAILURE);
|
|
}
|
|
|
|
while (1) {
|
|
RETRY_GET_FRAME:
|
|
if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_STOP)
|
|
break;
|
|
|
|
s32Ret = CVI_VDEC_GetFrame(
|
|
pstVdecThreadParam->s32ChnId,
|
|
&stVFrame,
|
|
pstVdecThreadParam->s32MilliSec);
|
|
if (s32Ret == CVI_SUCCESS) {
|
|
for (int i = 0; i < 3; i++) {
|
|
if (stVFrame.stVFrame.pu8VirAddr[i])
|
|
CVI_SYS_IonInvalidateCache(stVFrame.stVFrame.u64PhyAddr[i],
|
|
stVFrame.stVFrame.pu8VirAddr[i],
|
|
stVFrame.stVFrame.u32Stride[i] * stVFrame.stVFrame.u32Height);
|
|
}
|
|
|
|
CVI_VDEC_DISP("PTS = %"PRId64", u32TimeRef = %d\n",
|
|
pstVFrame->u64PTS, pstVFrame->u32TimeRef);
|
|
|
|
if (pstVdecThreadParam->bDumpYUV == 1) {
|
|
if (s32Cnt == 0) {
|
|
SAVE_FILE_NAME(cSaveFile, pstVdecThreadParam->s32ChnId,
|
|
pstVdecThreadParam->cFileName, stVFrame.stVFrame.enPixelFormat);
|
|
CVI_VDEC_TRACE("SAVE_FILE_NAME %s\n\n", cSaveFile);
|
|
|
|
fp = fopen(cSaveFile, "wb");
|
|
if (fp == NULL) {
|
|
CVI_VDEC_ERR("chn %d can't open file %s\n",
|
|
pstVdecThreadParam->s32ChnId, cSaveFile);
|
|
return (CVI_VOID *)(CVI_FAILURE);
|
|
}
|
|
CVI_VDEC_TRACE("\033[0;34m chn %d saving yuv file:%s \033[0;39m\n",
|
|
pstVdecThreadParam->s32ChnId, cSaveFile);
|
|
}
|
|
|
|
write_yuv(fp, stVFrame.stVFrame);
|
|
} else {
|
|
md5Sum_update(&pstVdecThreadParam->tMD5Ctx, stVFrame.stVFrame);
|
|
}
|
|
|
|
s32Cnt++;
|
|
|
|
s32Ret = CVI_VDEC_ReleaseFrame(pstVdecThreadParam->s32ChnId, &stVFrame);
|
|
if (s32Ret != CVI_SUCCESS) {
|
|
CVI_VDEC_ERR("chn %d CVI_MPI_VDEC_ReleaseFrame fail for s32Ret=0x%x!\n",
|
|
pstVdecThreadParam->s32ChnId, s32Ret);
|
|
}
|
|
} else {
|
|
if (s32Ret == CVI_ERR_VDEC_BUSY) {
|
|
CVI_VDEC_TRACE("vdec getframe timeout...retry\n");
|
|
goto RETRY_GET_FRAME;
|
|
}
|
|
usleep(pstVdecThreadParam->s32IntervalTime);
|
|
}
|
|
}
|
|
|
|
if (pstVdecThreadParam->bDumpYUV == 1) {
|
|
if (fp != CVI_NULL)
|
|
fclose(fp);
|
|
}
|
|
|
|
CVI_VDEC_TRACE("\033[0;35m chn %d get pic thread return ... \033[0;39m\n", pstVdecThreadParam->s32ChnId);
|
|
|
|
return (CVI_VOID *)CVI_SUCCESS;
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_StartGetPic(VDEC_THREAD_PARAM_S *pstVdecGet,
|
|
pthread_t *pVdecThread)
|
|
{
|
|
struct sched_param param;
|
|
pthread_attr_t attr;
|
|
|
|
param.sched_priority = 80;
|
|
pthread_attr_init(&attr);
|
|
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
pthread_attr_setschedparam(&attr, ¶m);
|
|
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
pthread_create(pVdecThread, &attr, SAMPLE_COMM_VDEC_GetPic, (CVI_VOID *)pstVdecGet);
|
|
}
|
|
|
|
CVI_VOID SAMPLE_COMM_VDEC_StopGetPic(VDEC_THREAD_PARAM_S *pstVdecGet, pthread_t *pVdecThread)
|
|
{
|
|
pstVdecGet->eThreadCtrl = THREAD_CTRL_STOP;
|
|
if (*pVdecThread != 0) {
|
|
pthread_join(*pVdecThread, CVI_NULL);
|
|
*pVdecThread = 0;
|
|
}
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_SetVbMode(CVI_S32 VdecVbSrc)
|
|
{
|
|
if (VdecVbSrc == 0)
|
|
g_VdecVbSrc = VB_SOURCE_COMMON;
|
|
else if (VdecVbSrc == 3)
|
|
g_VdecVbSrc = VB_SOURCE_USER;
|
|
else {
|
|
CVI_VDEC_ERR("set source mode %d error\n", VdecVbSrc);
|
|
return CVI_FAILURE;
|
|
}
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_GetVbMode(CVI_VOID)
|
|
{
|
|
return g_VdecVbSrc;
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_Start(vdecChnCtx *pvdchnCtx)
|
|
{
|
|
VDEC_CHN_ATTR_S stChnAttr, *pstChnAttr = &stChnAttr;
|
|
VDEC_CHN VdecChn = pvdchnCtx->VdecChn;
|
|
SAMPLE_VDEC_ATTR *psvdattr = &pvdchnCtx->stSampleVdecAttr;
|
|
VDEC_CHN_PARAM_S stChnParam;
|
|
VDEC_MOD_PARAM_S stModParam;
|
|
|
|
pstChnAttr->enType = psvdattr->enType;
|
|
pstChnAttr->enMode = psvdattr->enMode;
|
|
pstChnAttr->u32PicWidth = psvdattr->u32Width;
|
|
pstChnAttr->u32PicHeight = psvdattr->u32Height;
|
|
pstChnAttr->u32StreamBufSize = ALIGN(psvdattr->u32Width * psvdattr->u32Height, 0x4000);
|
|
CVI_VDEC_MEM("u32StreamBufSize = 0x%X\n", pstChnAttr->u32StreamBufSize);
|
|
pstChnAttr->u32FrameBufCnt = psvdattr->u32FrameBufCnt;
|
|
|
|
if (psvdattr->enType == PT_JPEG || psvdattr->enType == PT_MJPEG) {
|
|
pstChnAttr->enMode = VIDEO_MODE_FRAME;
|
|
pstChnAttr->u32FrameBufSize = VDEC_GetPicBufferSize(
|
|
pstChnAttr->enType, psvdattr->u32Width, psvdattr->u32Height,
|
|
psvdattr->enPixelFormat, DATA_BITWIDTH_8, COMPRESS_MODE_NONE);
|
|
}
|
|
|
|
CVI_VDEC_TRACE("VdecChn = %d\n", VdecChn);
|
|
|
|
if (g_VdecVbSrc != VB_SOURCE_COMMON) {
|
|
CVI_VDEC_GetModParam(&stModParam);
|
|
stModParam.enVdecVBSource = g_VdecVbSrc;
|
|
CVI_VDEC_SetModParam(&stModParam);
|
|
}
|
|
|
|
if (pvdchnCtx->bCreateChn == CVI_FALSE) {
|
|
CHECK_CHN_RET(CVI_VDEC_CreateChn(VdecChn, pstChnAttr), VdecChn, "CVI_VDEC_CreateChn");
|
|
pvdchnCtx->bCreateChn = CVI_TRUE;
|
|
} else {
|
|
CHECK_CHN_RET(CVI_VDEC_SetChnAttr(VdecChn, pstChnAttr), VdecChn, "CVI_VDEC_SetChnAttr");
|
|
}
|
|
|
|
if (g_VdecVbSrc == VB_SOURCE_USER) {
|
|
VDEC_CHN_POOL_S stPool;
|
|
|
|
stPool.hPicVbPool = g_ahPicVbPool[VdecChn];
|
|
stPool.hTmvVbPool = g_ahTmvVbPool[VdecChn];
|
|
|
|
CVI_VDEC_AttachVbPool(VdecChn, &stPool);
|
|
}
|
|
|
|
CHECK_CHN_RET(CVI_VDEC_GetChnParam(VdecChn, &stChnParam), VdecChn, "CVI_VDEC_GetChnParam");
|
|
|
|
if (psvdattr->enType == PT_H264 || psvdattr->enType == PT_H265) {
|
|
#if 0
|
|
stChnParam.stVdecVideoParam.enDecMode = psvdattr->stSampleVdecVideo.enDecMode;
|
|
stChnParam.stVdecVideoParam.enCompressMode = COMPRESS_MODE_NONE;
|
|
stChnParam.stVdecVideoParam.enVideoFormat = VIDEO_FORMAT_TILE_64x16;
|
|
if (stChnParam.stVdecVideoParam.enDecMode == VIDEO_DEC_MODE_IPB) {
|
|
stChnParam.stVdecVideoParam.enOutputOrder = VIDEO_OUTPUT_ORDER_DISP;
|
|
} else {
|
|
stChnParam.stVdecVideoParam.enOutputOrder = VIDEO_OUTPUT_ORDER_DEC;
|
|
}
|
|
#endif
|
|
} else {
|
|
stChnParam.stVdecPictureParam.u32Alpha =
|
|
psvdattr->stSampleVdecPicture.u32Alpha;
|
|
}
|
|
stChnParam.enPixelFormat = psvdattr->enPixelFormat;
|
|
stChnParam.u32DisplayFrameNum = psvdattr->u32DisplayFrameNum;
|
|
|
|
CHECK_CHN_RET(CVI_VDEC_SetChnParam(VdecChn, &stChnParam), VdecChn, "CVI_MPI_VDEC_GetChnParam");
|
|
|
|
CHECK_CHN_RET(CVI_VDEC_StartRecvStream(VdecChn), VdecChn, "CVI_MPI_VDEC_StartRecvStream");
|
|
|
|
return CVI_SUCCESS;
|
|
}
|
|
|
|
CVI_S32 SAMPLE_COMM_VDEC_Stop(CVI_S32 s32ChnNum)
|
|
{
|
|
CVI_S32 i;
|
|
|
|
for (i = 0; i < s32ChnNum; i++) {
|
|
CHECK_CHN_RET(CVI_VDEC_StopRecvStream(i), i, "CVI_MPI_VDEC_StopRecvStream");
|
|
if (g_VdecVbSrc == VB_SOURCE_USER) {
|
|
CVI_VDEC_TRACE("detach in user mode\n");
|
|
CHECK_CHN_RET(CVI_VDEC_DetachVbPool(i), i, "CVI_VDEC_DetachVbPool");
|
|
}
|
|
CHECK_CHN_RET(CVI_VDEC_ResetChn(i), i, "CVI_MPI_VDEC_ResetChn");
|
|
CHECK_CHN_RET(CVI_VDEC_DestroyChn(i), i, "CVI_MPI_VDEC_DestroyChn");
|
|
}
|
|
|
|
return CVI_SUCCESS;
|
|
}
|