3825
- 收藏
- 点赞
- 分享
- 举报
非rtmp实现实时播放
本帖最后由 mengxp 于 2017-9-11 10:05 编辑
rtmp是一套标准协议,可以方便与其他程序对接。但是如果不需要考虑接口,只是自己使用的话,就不需要rtmp。
最简单的思路就是,从海思venc读出数据流不包装,直接通过tcp发出。解码程序收到数据流之后,直接送解码器,解出yuv数据直接送显示。
可见这种方案,不需要考虑什么时间戳之类的东西,就是直接干。
整套流程时延100ms
架构:
VI-----------VENC--------TCP send---------- TCP recv ----------官方SDK解码---------DirectDraw显示图像
贴个代码片段,
编码端(hi3516D)
void VencGetStream(VENC_CHN VeChn)
{
HI_S32 s32Ret;
int fdVenc, fdFile;
PAYLOAD_TYPE_E enType;
VENC_CHN_ATTR_S stVencChnAttr;
fdVenc = HI_MPI_VENC_GetFd(VeChn);
if(fdVenc < 0)
{
printf("VencGetStream: HI_MPI_VENC_GetFdfailed\n");
return;
}
s32Ret = HI_MPI_VENC_GetChnAttr(VeChn, &stVencChnAttr);
if (s32Ret)
{
printf("VencGetStream: HI_MPI_VENC_GetChnAttr chn[%d] failed with %#x!\n", VeChn, s32Ret);
return;
}
enType = stVencChnAttr.stVeAttr.enType;
if(UseNetwork)
{
fdFile = fdNetwork;
}
else
{
fdFile = open("/tmp/stream0.h265", O_CREAT | O_TRUNC | O_RDWR);
if(fdFile < 0)
{
printf("VencGetStream: create stream file failed!\n");
return;
}
}
printf("receiving stream, press enter to break\n");
while(1)
{
struct timeval tv;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fdVenc, &fds);
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = 2;
tv.tv_usec = 0;
s32Ret = select(fdVenc + 1, &fds, NULL, NULL, &tv);
if (s32Ret == 0)
continue; //timeout
if (s32Ret < 0)
{
printf("VencGetStream: select failed!\n");
break;
}
if(FD_ISSET(STDIN_FILENO, &fds))
{
char k = getchar();
if(k == '\n')
{
printf("user interupt!\n");
break;
}
}
if(FD_ISSET(fdVenc, &fds))
{
VENC_CHN_STAT_S stStat;
VENC_STREAM_S stStream;
//有数据来了,检查有多少包
s32Ret = HI_MPI_VENC_Query(VeChn, &stStat);
if (s32Ret)
{
printf("VencGetStream: HI_MPI_VENC_Query failed with %#x!\n", s32Ret);
break;
}
if(!stStat.u32CurPacks)
{
printf("NOTE: Current frame is NULL!\n");
continue;
}
//申请描述符内存
stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
if (!stStream.pstPack)
{
printf("malloc stream pack failed!\n");
break;
}
//获取描述符
stStream.u32PackCount = stStat.u32CurPacks;
s32Ret = HI_MPI_VENC_GetStream(VeChn, &stStream, HI_TRUE);
if (s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
printf("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);
break;
}
//保存流数据
switch(enType)
{
VENC_PACK_S* pstData;
char *pStream;
int StreamSize;
int i;
case PT_H264:
for (i = 0; i < stStream.u32PackCount; i++)
{
pStream = (char *)stStream.pstPack.pu8Addr + stStream.pstPack.u32Offset;
StreamSize = stStream.pstPack.u32Len - stStream.pstPack.u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read H264 Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_H265:
for (i = 0; i < stStream.u32PackCount; i++)
{
pStream = (char *)stStream.pstPack.pu8Addr + stStream.pstPack.u32Offset;
StreamSize = stStream.pstPack.u32Len - stStream.pstPack.u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read H265 Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_MJPEG:
for (i = 0; i < stStream.u32PackCount; i++)
{
pstData = &stStream.pstPack;
pStream = (char *)pstData->pu8Addr + pstData->u32Offset;
StreamSize = pstData->u32Len - pstData->u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read MJPEG Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_JPEG:
for (i = 0; i < stStream.u32PackCount; i++)
{
pstData = &stStream.pstPack;
pStream = (char *)pstData->pu8Addr + pstData->u32Offset;
StreamSize = pstData->u32Len - pstData->u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read JPEG Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
default:
break;
}
//释放流数据
s32Ret = HI_MPI_VENC_ReleaseStream(VeChn, &stStream);
if (s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
break;
}
//释放描述符
free(stStream.pstPack);
stStream.pstPack = NULL;
}
}
close(fdFile);
}
解码端只处理一个连接
int BufferDataOut(char *buf, int total, int len)
{
int restlen = total - len;
int i;
if(restlen <= 0)
return 0;
for(i = 0; i < restlen; i++)
{
buf = buf[restlen + i];
}
return restlen;
}
void NetListen()
{
WSADATA wsa;
SOCKET sock = INVALID_SOCKET;
char *RecvBuf = NULL;
ULONG RecvBufSize = 1024*1024;
do {
struct sockaddr_in sin;
int ret;
WSAStartup(0x101, &wsa);
RecvBuf = malloc(RecvBufSize);
if(!RecvBuf)
break;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
{
printf("NetListen: socket failed\n");
break;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(6666);
ret = bind(sock, (struct sockaddr *)&sin, sizeof(sin));
if(ret)
{
printf("NetListen: bind failed\n");
break;
}
ret = listen(sock, 1);
if(ret)
{
printf("NetListen: listen failed\n");
break;
}
while(1)
{
struct sockaddr_in sin_accept;
int sinlen = sizeof(sin_accept);
SOCKET recvsock = INVALID_SOCKET;
IH265DEC_HANDLE hDecoder;
int RecvTotalLen = 0;
recvsock = accept(sock, (struct sockaddr *)&sin_accept, &sinlen);
if(recvsock == INVALID_SOCKET)
continue;
hDecoder = CreateH265Decoder(FALSE, TRUE);
if(!hDecoder)
{
closesocket(recvsock);
continue;
}
while(1)
{
char *buf = RecvBuf + RecvTotalLen;
int bufsize = RecvBufSize - RecvTotalLen;
int len, declen, err;
ULONG dwTick = GetTickCount();
char tmp[256];
len = recv(recvsock, buf, bufsize, 0);
if(len <= 0)
{
break;
}
RecvTotalLen += len;
RecvBytes += len;
if(dwTick - RecvLastTick >= 1000)
{
RecvBytesThisSec = RecvBytes - RecvBytesLastSec;
RecvBytesLastSec = RecvBytes;
RecvLastTick = dwTick;
sprintf(tmp, "Hi3516 H265 decode sample recv: %d KB/s", RecvBytesThisSec / 1024);
SetWindowText(hWinMain, tmp);
}
err = H265StreamIn(hDecoder, RecvBuf, RecvTotalLen, &declen);
if(err)
{
break;
}
RecvTotalLen = BufferDataOut(RecvBuf, RecvTotalLen, declen);
}
closesocket(recvsock);
DestroyH265Decoder(hDecoder);
}
} while (0);
if(sock != INVALID_SOCKET)
closesocket(sock);
}
BOOL DDraw(PDDRAW_HANDLE pHandle, IH265DEC_OUTARGS *pDecArgs)
{
DDSURFACEDESC2 ddsd; // DirectDraw 表面描述
RECT rcDst; // 目标区域
RECT rcSrc; // 源区域
HRESULT hr; // DirectDraw 函数返回值
LPBYTE lpSurf;
ULONG i, pos;
if(!pHandle || !pHandle->pDirectDraw || !pHandle->pSurfaceOffScreen || !pHandle->pSurfacePrimary)
return FALSE;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
hr = pHandle->pSurfaceOffScreen->Lock(NULL, &ddsd,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL);
if(hr != S_OK)
return FALSE;
lpSurf = (LPBYTE)ddsd.lpSurface;
for(i = 0, pos = 0; i < pDecArgs->uiDecHeight; i++, pos += pDecArgs->uiDecWidth)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[0] + i * pDecArgs->uiYStride, pDecArgs->uiDecWidth);
lpSurf += ddsd.lPitch;
}
for(i = 0, pos = 0; i < ((pDecArgs->uiDecHeight) >> 1); i++, pos += pDecArgs->uiDecWidth >> 1)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[2] + i * pDecArgs->uiUVStride, pDecArgs->uiDecWidth >> 1);
lpSurf += ddsd.lPitch >> 1;
}
for(i = 0, pos = 0; i < ((pDecArgs->uiDecHeight) >> 1); i++, pos += pDecArgs->uiDecWidth >> 1)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[1] + i * pDecArgs->uiUVStride, pDecArgs->uiDecWidth >> 1);
lpSurf += ddsd.lPitch >> 1;
}
pHandle->pSurfaceOffScreen->Unlock(NULL);
// Blt到主表面上
rcSrc.left = 0;
rcSrc.top = 0;
rcSrc.right = ddsd.dwWidth;
rcSrc.bottom = ddsd.dwHeight;
GetClientRect(pHandle->hWnd,&rcDst);
ClientToScreen(pHandle->hWnd, (LPPOINT)&rcDst.left);
ClientToScreen(pHandle->hWnd, (LPPOINT)&rcDst.right);
while(1)
{
hr = pHandle->pSurfacePrimary->Blt(&rcDst, pHandle->pSurfaceOffScreen, &rcSrc, DDBLT_WAIT, NULL);
if(hr == DDERR_SURFACELOST)
{
pHandle->pSurfacePrimary->Restore();
pHandle->pSurfaceOffScreen->Restore();
}
if(hr != DDERR_WASSTILLDRAWING)
break;
}
return TRUE;
}
int H265StreamIn(IH265DEC_HANDLE hDecoder, char *pStream, int iFileLen, int *pFrameTotalLen)
{
IH265DEC_INARGS stInArgs;
IH265DEC_OUTARGS stOutArgs = {0};
int FrameTotalLen = 0;
int DecodeEnd = 0;
int ret = 0;
while(!DecodeEnd)
{
UINT32 iNaluLen;
H265DecLoadAU((UINT8 *)pStream, iFileLen, &iNaluLen);
if(iNaluLen > 0)
FrameTotalLen += iNaluLen;
else
break;
stInArgs.eDecodeMode = IH265D_DECODE;
stInArgs.pStream = (UINT8 *)pStream;
stInArgs.uiStreamLen = iNaluLen;
pStream += iNaluLen;
iFileLen -= iNaluLen;
stOutArgs.eDecodeStatus = (HW265D_DECODESTATUS)-1;
stOutArgs.uiBytsConsumed = 0;
// if return value if IH265D_NEED_MORE_BITS, read more bits from files
while(stOutArgs.eDecodeStatus != IH265D_NEED_MORE_BITS)
{
INT32 iRet;
// decode end
if(stOutArgs.eDecodeStatus == IH265D_NO_PICTURE)
{
DbgPrint("IH265D_NO_PICTURE !!!!!!\n");
DecodeEnd = 1;
ret = -1;
break;
}
// output decoded pictures
if (stOutArgs.eDecodeStatus == IH265D_GETDISPLAY)
{
DDraw(pDDraw, &stOutArgs);
iFrameIdx++;
}
stInArgs.pStream += stOutArgs.uiBytsConsumed;
stInArgs.uiStreamLen -= stOutArgs.uiBytsConsumed;
iRet = IHW265D_DecodeFrame(hDecoder, &stInArgs, &stOutArgs);
if ((iRet != IHW265D_OK) && (iRet != IHW265D_NEED_MORE_BITS))
{
DbgPrint("IHW265D_DecodeFrame FAILED !!!!!! %d %d\n", iRet, iFrameIdx);
DecodeEnd = 1;
ret = -1;
break;
}
}
}
*pFrameTotalLen = FrameTotalLen;
return ret;
}
rtmp是一套标准协议,可以方便与其他程序对接。但是如果不需要考虑接口,只是自己使用的话,就不需要rtmp。
最简单的思路就是,从海思venc读出数据流不包装,直接通过tcp发出。解码程序收到数据流之后,直接送解码器,解出yuv数据直接送显示。
可见这种方案,不需要考虑什么时间戳之类的东西,就是直接干。
整套流程时延100ms
架构:
VI-----------VENC--------TCP send---------- TCP recv ----------官方SDK解码---------DirectDraw显示图像
贴个代码片段,
编码端(hi3516D)
void VencGetStream(VENC_CHN VeChn)
{
HI_S32 s32Ret;
int fdVenc, fdFile;
PAYLOAD_TYPE_E enType;
VENC_CHN_ATTR_S stVencChnAttr;
fdVenc = HI_MPI_VENC_GetFd(VeChn);
if(fdVenc < 0)
{
printf("VencGetStream: HI_MPI_VENC_GetFdfailed\n");
return;
}
s32Ret = HI_MPI_VENC_GetChnAttr(VeChn, &stVencChnAttr);
if (s32Ret)
{
printf("VencGetStream: HI_MPI_VENC_GetChnAttr chn[%d] failed with %#x!\n", VeChn, s32Ret);
return;
}
enType = stVencChnAttr.stVeAttr.enType;
if(UseNetwork)
{
fdFile = fdNetwork;
}
else
{
fdFile = open("/tmp/stream0.h265", O_CREAT | O_TRUNC | O_RDWR);
if(fdFile < 0)
{
printf("VencGetStream: create stream file failed!\n");
return;
}
}
printf("receiving stream, press enter to break\n");
while(1)
{
struct timeval tv;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fdVenc, &fds);
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = 2;
tv.tv_usec = 0;
s32Ret = select(fdVenc + 1, &fds, NULL, NULL, &tv);
if (s32Ret == 0)
continue; //timeout
if (s32Ret < 0)
{
printf("VencGetStream: select failed!\n");
break;
}
if(FD_ISSET(STDIN_FILENO, &fds))
{
char k = getchar();
if(k == '\n')
{
printf("user interupt!\n");
break;
}
}
if(FD_ISSET(fdVenc, &fds))
{
VENC_CHN_STAT_S stStat;
VENC_STREAM_S stStream;
//有数据来了,检查有多少包
s32Ret = HI_MPI_VENC_Query(VeChn, &stStat);
if (s32Ret)
{
printf("VencGetStream: HI_MPI_VENC_Query failed with %#x!\n", s32Ret);
break;
}
if(!stStat.u32CurPacks)
{
printf("NOTE: Current frame is NULL!\n");
continue;
}
//申请描述符内存
stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
if (!stStream.pstPack)
{
printf("malloc stream pack failed!\n");
break;
}
//获取描述符
stStream.u32PackCount = stStat.u32CurPacks;
s32Ret = HI_MPI_VENC_GetStream(VeChn, &stStream, HI_TRUE);
if (s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
printf("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);
break;
}
//保存流数据
switch(enType)
{
VENC_PACK_S* pstData;
char *pStream;
int StreamSize;
int i;
case PT_H264:
for (i = 0; i < stStream.u32PackCount; i++)
{
pStream = (char *)stStream.pstPack.pu8Addr + stStream.pstPack.u32Offset;
StreamSize = stStream.pstPack.u32Len - stStream.pstPack.u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read H264 Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_H265:
for (i = 0; i < stStream.u32PackCount; i++)
{
pStream = (char *)stStream.pstPack.pu8Addr + stStream.pstPack.u32Offset;
StreamSize = stStream.pstPack.u32Len - stStream.pstPack.u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read H265 Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_MJPEG:
for (i = 0; i < stStream.u32PackCount; i++)
{
pstData = &stStream.pstPack;
pStream = (char *)pstData->pu8Addr + pstData->u32Offset;
StreamSize = pstData->u32Len - pstData->u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read MJPEG Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
case PT_JPEG:
for (i = 0; i < stStream.u32PackCount; i++)
{
pstData = &stStream.pstPack;
pStream = (char *)pstData->pu8Addr + pstData->u32Offset;
StreamSize = pstData->u32Len - pstData->u32Offset;
write(fdFile, pStream, StreamSize);
printf("Read JPEG Stream %d bytes @ %p\n", StreamSize, pStream);
}
break;
default:
break;
}
//释放流数据
s32Ret = HI_MPI_VENC_ReleaseStream(VeChn, &stStream);
if (s32Ret)
{
free(stStream.pstPack);
stStream.pstPack = NULL;
break;
}
//释放描述符
free(stStream.pstPack);
stStream.pstPack = NULL;
}
}
close(fdFile);
}
解码端只处理一个连接
int BufferDataOut(char *buf, int total, int len)
{
int restlen = total - len;
int i;
if(restlen <= 0)
return 0;
for(i = 0; i < restlen; i++)
{
buf = buf[restlen + i];
}
return restlen;
}
void NetListen()
{
WSADATA wsa;
SOCKET sock = INVALID_SOCKET;
char *RecvBuf = NULL;
ULONG RecvBufSize = 1024*1024;
do {
struct sockaddr_in sin;
int ret;
WSAStartup(0x101, &wsa);
RecvBuf = malloc(RecvBufSize);
if(!RecvBuf)
break;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
{
printf("NetListen: socket failed\n");
break;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(6666);
ret = bind(sock, (struct sockaddr *)&sin, sizeof(sin));
if(ret)
{
printf("NetListen: bind failed\n");
break;
}
ret = listen(sock, 1);
if(ret)
{
printf("NetListen: listen failed\n");
break;
}
while(1)
{
struct sockaddr_in sin_accept;
int sinlen = sizeof(sin_accept);
SOCKET recvsock = INVALID_SOCKET;
IH265DEC_HANDLE hDecoder;
int RecvTotalLen = 0;
recvsock = accept(sock, (struct sockaddr *)&sin_accept, &sinlen);
if(recvsock == INVALID_SOCKET)
continue;
hDecoder = CreateH265Decoder(FALSE, TRUE);
if(!hDecoder)
{
closesocket(recvsock);
continue;
}
while(1)
{
char *buf = RecvBuf + RecvTotalLen;
int bufsize = RecvBufSize - RecvTotalLen;
int len, declen, err;
ULONG dwTick = GetTickCount();
char tmp[256];
len = recv(recvsock, buf, bufsize, 0);
if(len <= 0)
{
break;
}
RecvTotalLen += len;
RecvBytes += len;
if(dwTick - RecvLastTick >= 1000)
{
RecvBytesThisSec = RecvBytes - RecvBytesLastSec;
RecvBytesLastSec = RecvBytes;
RecvLastTick = dwTick;
sprintf(tmp, "Hi3516 H265 decode sample recv: %d KB/s", RecvBytesThisSec / 1024);
SetWindowText(hWinMain, tmp);
}
err = H265StreamIn(hDecoder, RecvBuf, RecvTotalLen, &declen);
if(err)
{
break;
}
RecvTotalLen = BufferDataOut(RecvBuf, RecvTotalLen, declen);
}
closesocket(recvsock);
DestroyH265Decoder(hDecoder);
}
} while (0);
if(sock != INVALID_SOCKET)
closesocket(sock);
}
BOOL DDraw(PDDRAW_HANDLE pHandle, IH265DEC_OUTARGS *pDecArgs)
{
DDSURFACEDESC2 ddsd; // DirectDraw 表面描述
RECT rcDst; // 目标区域
RECT rcSrc; // 源区域
HRESULT hr; // DirectDraw 函数返回值
LPBYTE lpSurf;
ULONG i, pos;
if(!pHandle || !pHandle->pDirectDraw || !pHandle->pSurfaceOffScreen || !pHandle->pSurfacePrimary)
return FALSE;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
hr = pHandle->pSurfaceOffScreen->Lock(NULL, &ddsd,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL);
if(hr != S_OK)
return FALSE;
lpSurf = (LPBYTE)ddsd.lpSurface;
for(i = 0, pos = 0; i < pDecArgs->uiDecHeight; i++, pos += pDecArgs->uiDecWidth)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[0] + i * pDecArgs->uiYStride, pDecArgs->uiDecWidth);
lpSurf += ddsd.lPitch;
}
for(i = 0, pos = 0; i < ((pDecArgs->uiDecHeight) >> 1); i++, pos += pDecArgs->uiDecWidth >> 1)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[2] + i * pDecArgs->uiUVStride, pDecArgs->uiDecWidth >> 1);
lpSurf += ddsd.lPitch >> 1;
}
for(i = 0, pos = 0; i < ((pDecArgs->uiDecHeight) >> 1); i++, pos += pDecArgs->uiDecWidth >> 1)
{
memcpy(lpSurf, pDecArgs->pucOutYUV[1] + i * pDecArgs->uiUVStride, pDecArgs->uiDecWidth >> 1);
lpSurf += ddsd.lPitch >> 1;
}
pHandle->pSurfaceOffScreen->Unlock(NULL);
// Blt到主表面上
rcSrc.left = 0;
rcSrc.top = 0;
rcSrc.right = ddsd.dwWidth;
rcSrc.bottom = ddsd.dwHeight;
GetClientRect(pHandle->hWnd,&rcDst);
ClientToScreen(pHandle->hWnd, (LPPOINT)&rcDst.left);
ClientToScreen(pHandle->hWnd, (LPPOINT)&rcDst.right);
while(1)
{
hr = pHandle->pSurfacePrimary->Blt(&rcDst, pHandle->pSurfaceOffScreen, &rcSrc, DDBLT_WAIT, NULL);
if(hr == DDERR_SURFACELOST)
{
pHandle->pSurfacePrimary->Restore();
pHandle->pSurfaceOffScreen->Restore();
}
if(hr != DDERR_WASSTILLDRAWING)
break;
}
return TRUE;
}
int H265StreamIn(IH265DEC_HANDLE hDecoder, char *pStream, int iFileLen, int *pFrameTotalLen)
{
IH265DEC_INARGS stInArgs;
IH265DEC_OUTARGS stOutArgs = {0};
int FrameTotalLen = 0;
int DecodeEnd = 0;
int ret = 0;
while(!DecodeEnd)
{
UINT32 iNaluLen;
H265DecLoadAU((UINT8 *)pStream, iFileLen, &iNaluLen);
if(iNaluLen > 0)
FrameTotalLen += iNaluLen;
else
break;
stInArgs.eDecodeMode = IH265D_DECODE;
stInArgs.pStream = (UINT8 *)pStream;
stInArgs.uiStreamLen = iNaluLen;
pStream += iNaluLen;
iFileLen -= iNaluLen;
stOutArgs.eDecodeStatus = (HW265D_DECODESTATUS)-1;
stOutArgs.uiBytsConsumed = 0;
// if return value if IH265D_NEED_MORE_BITS, read more bits from files
while(stOutArgs.eDecodeStatus != IH265D_NEED_MORE_BITS)
{
INT32 iRet;
// decode end
if(stOutArgs.eDecodeStatus == IH265D_NO_PICTURE)
{
DbgPrint("IH265D_NO_PICTURE !!!!!!\n");
DecodeEnd = 1;
ret = -1;
break;
}
// output decoded pictures
if (stOutArgs.eDecodeStatus == IH265D_GETDISPLAY)
{
DDraw(pDDraw, &stOutArgs);
iFrameIdx++;
}
stInArgs.pStream += stOutArgs.uiBytsConsumed;
stInArgs.uiStreamLen -= stOutArgs.uiBytsConsumed;
iRet = IHW265D_DecodeFrame(hDecoder, &stInArgs, &stOutArgs);
if ((iRet != IHW265D_OK) && (iRet != IHW265D_NEED_MORE_BITS))
{
DbgPrint("IHW265D_DecodeFrame FAILED !!!!!! %d %d\n", iRet, iFrameIdx);
DecodeEnd = 1;
ret = -1;
break;
}
}
}
*pFrameTotalLen = FrameTotalLen;
return ret;
}
我来回答
回答7个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2016-06-07 17:41:39
-
2020-09-29 10:31:19
-
2018-12-18 14:24:48
-
2018-12-07 11:17:50
-
2018-12-07 14:10:03
-
142014-09-25 20:42:04
-
2021-01-21 16:21:48
-
2018-10-20 09:52:13
-
2016-08-12 10:41:17
-
2019-03-15 11:35:34
-
2018-06-04 17:41:20
-
2020-10-06 12:22:50
-
2017-07-21 16:44:14
-
2014-08-09 15:15:11
-
02018-12-12 10:10:29
-
2012-12-24 14:14:27
-
2016-07-24 13:53:57
-
2015-03-20 17:32:41
-
2015-03-19 09:51:54
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认