从264文件中读取Nal,一般用于测试的时候H264输入源:
参考:https://blog.csdn.net/leixiaohua1020/article/details/17933821
分辨率较大的话需要修改 READH264_MAXFRAME_SIZE,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PTR_NULL (void *)0
#define _RET_OK 0
#define _RET_ERR -1
#define _RET_MEM -2
#define _RET_PARAM -3
#define _RET_FILE -4
#define _RET_SUPPFRAME -5
#define READH264_MAGIC 0x48323634
#define READH264_MAXFRAME_SIZE 1920*1080*3/2
#define READH264_CACHE_SIZE (READH264_MAXFRAME_SIZE + 16)
#define H264CHECK_RET(ret) if(ret < 0) {return ret;}
typedef struct stru_READHANDLE
{
int iMagic;
FILE *fp;
int bFileEnd;
int iNaluEndPos;
int iCachePos;
int iCacheSize;
int iFrameSize;
unsigned char *pucCache;
unsigned char *pucFrame;
}ST_READHANDLE;
static int FindStartCode(unsigned char *scData)
{
if ((0==scData[0]) && (0==scData[1]) &&
(((0==scData[2]) && (1 == scData[3])) || (1==scData[2])) )
{
return 1;
}
return 0;
}
static int GetNaluDataLen(int startPos, int h264BitsSize, unsigned char *h264Bits)
{
int parsePos = 0;
parsePos = startPos;
while (parsePos < h264BitsSize)
{
if (FindStartCode(&h264Bits[parsePos]))
{
return parsePos - startPos;
}
else
{
parsePos++;
}
}
return parsePos - startPos; // if file is end
}
static int initReadHandle(ST_READHANDLE **pphandle)
{
ST_READHANDLE *phandle = (ST_READHANDLE*)malloc(sizeof(ST_READHANDLE));
if (NULL == phandle) return _RET_MEM;
memset(phandle, 0, sizeof(ST_READHANDLE));
phandle->iMagic = READH264_MAGIC;
phandle->pucCache = malloc(READH264_CACHE_SIZE);
if (NULL == phandle->pucCache)
{
free(phandle);
return _RET_MEM;
}
phandle->iCacheSize = READH264_CACHE_SIZE;
phandle->pucFrame = malloc(READH264_MAXFRAME_SIZE);
if (NULL == phandle->pucFrame)
{
free(phandle->pucCache);
free(phandle);
return _RET_MEM;
}
phandle->iFrameSize = READH264_MAXFRAME_SIZE;
*pphandle = phandle;
printf("init ok %p\n",*pphandle);
return _RET_OK;
}
static int checkHandle(ST_READHANDLE **pphandle)
{
if (NULL == pphandle) return _RET_ERR;
if (NULL == *pphandle) H264CHECK_RET(initReadHandle(pphandle));
if ((READH264_MAXFRAME_SIZE != (*pphandle)->iFrameSize)) return _RET_PARAM;
return _RET_OK;
}
static int read246File(ST_READHANDLE *phandle, unsigned char *pucfileName)
{
int iReadLen = 0;
if (phandle->bFileEnd) return _RET_OK;
if (NULL == phandle->fp)
{
if ((NULL == pucfileName) || (strlen((const char *)pucfileName) <=0)) return _RET_PARAM;
phandle->fp = fopen((const char *)pucfileName,"rb");
if (NULL == phandle->fp) return _RET_FILE;
}
iReadLen = fread(&phandle->pucCache[phandle->iCachePos], 1, (phandle->iCacheSize - phandle->iCachePos), phandle->fp);
if (iReadLen != phandle->iCacheSize - phandle->iCachePos)
{
fclose(phandle->fp);
phandle->fp = NULL;
phandle->bFileEnd = 1;
if (iReadLen < 0) iReadLen = 0;
}
phandle->iCachePos += iReadLen;
return _RET_OK;
}
static int getFrameLen(ST_READHANDLE *phandle)
{
if (FindStartCode(phandle->pucCache))
return GetNaluDataLen(3, phandle->iCachePos, phandle->pucCache) + 3;
return _RET_ERR;
}
static int Get246Frame(ST_READHANDLE *phandle, unsigned char **ppbuf, int *iLen)
{
int iRet = 0;
*iLen = 0;
if (phandle->iCachePos <= 0)
{
printf("read end CacheLen:%d\n", phandle->iCachePos);
return 0;
}
iRet = getFrameLen(phandle);
H264CHECK_RET(iRet);
if (iRet > READH264_MAXFRAME_SIZE)
return _RET_SUPPFRAME;
memcpy(phandle->pucFrame, phandle->pucCache, iRet);
if (phandle->iCachePos > iRet)
{
memmove(phandle->pucCache, phandle->pucCache+iRet, phandle->iCachePos-iRet);
phandle->iCachePos = phandle->iCachePos - iRet;
}
else
{
printf("read end CacheLen:%d FrameLen:%d\n",phandle->iCachePos, iRet);
phandle->iCachePos = 0;
}
*ppbuf = phandle->pucFrame;
*iLen = iRet;
return iRet;
}
int read264Nalu(void **pphandle, unsigned char *pucfileName,unsigned char **ppbuf, int *iLen)
{
if ((NULL == ppbuf) || (NULL == iLen))
return _RET_PARAM;
H264CHECK_RET(checkHandle((ST_READHANDLE **)pphandle));
//printf("check ok %p-%p \n",pphandle, *pphandle);
H264CHECK_RET(read246File((ST_READHANDLE *)*pphandle, pucfileName));
return Get246Frame(*pphandle, ppbuf, iLen);
}
int releaseReadHanle(void **pphandle)
{
ST_READHANDLE *phandle = NULL;
if ((NULL == pphandle) && (NULL == *pphandle))
return _RET_ERR;
phandle = *pphandle;
if (phandle->fp)
fclose(phandle->fp);
if (phandle->pucCache)
free(phandle->pucCache);
if (phandle->pucFrame)
free(phandle->pucFrame);
free(phandle);
*pphandle = NULL;
printf("releaseReadHanle\n");
return _RET_OK;
}
#if 0
int main(int argc, char *argv[])
{
void *pReadHandle = NULL;
unsigned char *pucReadFrame = NULL;
int iFrameLen = 0;
FILE *fp = fopen(argv[2], "wb");
if (!fp)
{
printf("open file[%s] error!\n", argv[2]);
return -1;
}
while (read264Nalu(&pReadHandle,argv[1], &pucReadFrame, &iFrameLen) > 0)
{
printf("Get FrameLen:%d \n",iFrameLen);
fwrite(pucReadFrame, 1, iFrameLen, fp);
}
releaseReadHanle(&pReadHandle);
fclose(fp);
return 0;
}
#endif