目录
- 原理
- 分析
- 代码实现
- .c
- .h
- 效果
原理
视频编解码——NAL Unit结构分析
分析
- 1、首先去掉起始码得到NALU实际数据
- 2、分离出NALU中一个字节的header
-
- 1bit禁止位、2bitNRI、5bitTYPE
- 3、解析剩余NALU的body部分
-
- EBSP去除03->RBSP
代码实现
.c
#include "LUX_TEST_Get264.h"LUX_OSD_DataPoint dataPoint;
LUX_OSD_FilePoint filePoint;
int offset = 0;/*** @description: 初始化* @param [in] void* @return */
int LUX_TEST_Init(void)
{int ret = LUX_SUCCESS;int len = 0;do{/*打开264文件*/filePoint.h264File = fopen(LUX_TEST_File, "r");if (NULL == filePoint.h264File){printf("fopen h264file failed\n");perror("why");ret = LUX_FAILED;break;}dataPoint.h264Data = malloc(LUX_TEST_FileSpace);if (NULL == dataPoint.h264Data){printf("malloc dataPoint.h264Data failed\n");perror("why");ret = LUX_FAILED;break;}/*存放h264实际数据*/filePoint.saveH264 = fopen(LUX_TEST_DestFile,"w+"); if(NULL == filePoint.saveH264){printf("fopen LUX_FONT_WRITE_FILE failed\n");}/*读入内存*/len = fread(dataPoint.h264Data, 1, LUX_TEST_FileSpace, filePoint.h264File);if (0 == len){printf("fread dataPoint.h264Data failed\n");perror("why");ret = LUX_FAILED;break;}}while(0);return ret;
}/*** @description: 抓取h264数据并存储* @param [in] void* @return */
int LUX_TEST_Get264Data(void)
{int ret = LUX_SUCCESS;int getDataOffset = 0;int len = 0;do{while(1){if (*(dataPoint.h264Data + offset) == 0 && *(dataPoint.h264Data + offset + 1) == 0){if (*(dataPoint.h264Data + offset + 2) == 1){/*0x 00 00 01*///TODObreak;}else if (*(dataPoint.h264Data + offset + 2) == 0 && *(dataPoint.h264Data + offset + 3) == 1){/*0x 00 00 00 01*/do{getDataOffset++;len = fwrite(dataPoint.h264Data + offset + 3 + getDataOffset, 1, 1, filePoint.saveH264);if (len <= 0){printf("fwrite dataPoint.h264Data failed\n");perror("why");return LUX_FAILED;}if (*(dataPoint.h264Data + 3 + getDataOffset + 1) == 0 && *(dataPoint.h264Data + 3 + getDataOffset + 2) == 0 && *(dataPoint.h264Data + 3 + getDataOffset + 3) == 0 && *(dataPoint.h264Data + 3 + getDataOffset + 4) == 1)break;}while (1);break;}}offset++;}}while(0);fclose(filePoint.saveH264);return ret;
}/*** @description: 解析NALU的header* @param [in] void* @return */
int LUX_TEST_Parise()
{int ret = LUX_SUCCESS;struct stat getSize_ST;int naluSize = 0;int len = 0;char header = 0;char nal_ref_idc = 0;char nal_unit_type = 0;int i = 0;int jugdeTime = 0;int offset = 1;int restore = 0;do{/*获取nalu数据大小*/ret = stat(LUX_TEST_DestFile, &getSize_ST);if (-1 == ret){perror("get file size failed");break;}naluSize = (int)getSize_ST.st_size;/*存放h264数据*/dataPoint.naluData = malloc(naluSize);if (NULL == dataPoint.naluData){printf("malloc dataPoint.naluData failed\n");perror("why");ret = LUX_FAILED;break;}filePoint.saveH264 = fopen(LUX_TEST_DestFile, "r");if (NULL == filePoint.saveH264){printf("fopen saveH264 failed\n");perror("why");ret = LUX_FAILED;break;}len = fread(dataPoint.naluData, 1, naluSize, filePoint.saveH264);if (0 == len){printf("fread dataPoint.naluData failed\n");perror("why");ret = LUX_FAILED;break;}fclose(filePoint.saveH264);/*解析header*/header = *dataPoint.naluData;nal_ref_idc = (header | 0x60) >> 5;nal_unit_type = (header & 0x1f);printf("==================\n");printf("nal_ref_idc = %x\n",nal_ref_idc);printf("nal_unit_type = %x\n",nal_unit_type);printf("++++++++++++++++++\n");/*解析body*/jugdeTime = naluSize - 3;/*header、003*/for (i = 0; i < jugdeTime; i++){if (*(dataPoint.naluData + offset) == 0 && *(dataPoint.naluData + offset + 1) == 0 &&*(dataPoint.naluData + offset + 2) == 3){while ((offset + 2 + restore + 1) < jugdeTime){*(dataPoint.naluData + offset + 2 + restore) = *(dataPoint.naluData + offset + 2 + restore + 1);restore++;}break;}elseoffset++;}i = 0;printf("RBSP = ");for (i = 0; i < (naluSize - 1); i++){printf("%x ", *(dataPoint.naluData + 1 + i));i++;}printf("\n==================\n");}while (0);return ret;
}
/*** @description: 去初始化* @param [in] void* @return */
int LUX_TEST_DeInit(void)
{free(dataPoint.h264Data);fclose(filePoint.h264File);}int main()
{int ret = LUX_FAILED;ret = LUX_TEST_Init();if(LUX_FAILED == ret){printf("LUX_TEST_Init error\n");return LUX_FAILED;}ret = LUX_TEST_Get264Data();if(LUX_FAILED == ret){printf("LUX_TEST_Get264Data error\n");return LUX_FAILED;}ret = LUX_TEST_Parise();if(LUX_FAILED == ret){printf("LUX_TEST_Parise error\n");return LUX_FAILED;}ret = LUX_TEST_DeInit();if(LUX_FAILED == ret){printf("LUX_TEST_DeInit error\n");return LUX_FAILED;}return LUX_SUCCESS;
}
.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>#define LUX_TEST_File "test.264"
#define LUX_TEST_DestFile "destFile"#define LUX_TEST_FileSpace 0x2040
#define LUX_SUCCESS 0
#define LUX_FAILED -1typedef struct
{char *h264Data; //YUVchar *naluData; //去除起始码分理处的nalu数据
}LUX_OSD_DataPoint;typedef struct
{FILE *h264File; //打开264FILE *saveH264; //存h264实际数据
}LUX_OSD_FilePoint;/*** @description: 初始化* @param [in] void* @return */
int LUX_TEST_Init(void);/*** @description: 抓取h264数据并存储* @param [in] void* @return */
int LUX_TEST_Get264Data(void);/*** @description: 解析NALU* @param [in] void* @return */
int LUX_TEST_Parise();/*** @description: 去初始化* @param [in] void* @return */
int LUX_TEST_DeInit(void);