read H264 Nal

本文介绍了一种从H264文件中读取并解析NAL单元的方法,包括初始化读取句柄、查找起始码、获取NAL单元长度等功能。适用于大分辨率视频的测试场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值