从NAL UNIT中对rbsp获取的原理如图所示,此为NAL UNIT解析的架构图
头文件
#ifndef __NAL_UNIT_H__
#define __NAL_UNIT_H__#include <stdio.h>typedef struct Nal_Unit_Fops {int (*find_nal_unit_data)(FILE *file);int (*find_nal_unit_head)(char (*QueueBuf)[],int *pos,char *character,FILE *file);void (*find_nal_unit_type)(char (*QueueBuf)[],int *pos,char *character,FILE *file);int (*nal_unit_ebsp_to_rbsp)(char (*QueueBuf)[],int *pos);
} NAL_UNIT_OPS, *P_NAL_UNIT_OPS; typedef struct File_Fops {int (*open_file)(FILE **file,const char *file_path);int (*close_file)(FILE *file);
} FILE_OPS, *P_FILE_OPS;P_NAL_UNIT_OPS NalUnitOps = NULL;
P_FILE_OPS FileOps = NULL;#endif
主文件
#include "Nal_Unit.h"/* ebsp 转化为rbsp */
static int nal_unit_ebsp_to_rbsp(char (*QueueBuf)[],int *pos)
{int IsExtended = 0;/* 寻找ebsp流中是否存在00 00 03字符,如果存在则需要将其03去除,从而转化为rbsp */if(((*QueueBuf)[((*pos)+0)%3] == 0) && ((*QueueBuf)[((*pos)+1)%3] == 0) && ((*QueueBuf)[((*pos)+2)%3] == 3)) {IsExtended = 1;}return IsExtended;
}/* 寻找当前nal unit类型 */
static void find_nal_unit_type(char (*QueueBuf)[],int *pos,char *character,FILE *file)
{int Type = 0;fread(character,1,1,file);(*QueueBuf)[((*pos)++)%3] = *character;Type = *character & 0x1F; //printf("Type = %d\n",Type);
}/* 寻找nal unit头部信息*/
static int find_nal_unit_head(char (*QueueBuf)[],int *pos,char *character,FILE *file)
{fread(character,1,1,file);/* (1)给char buf先赋值 */(*QueueBuf)[((*pos)++)%3] = *character;if((*pos) < 3) {return -1;} else {if(((*QueueBuf)[((*pos)+0)%3] == 0) && ((*QueueBuf)[((*pos)+1)%3] == 0) && ((*QueueBuf)[((*pos)+2)%3] == 1)) {/* (2)寻找00 00 00 01形式的起始码 *///printf("find nal unit 001 pos = %d\n",pos);return 1;} else if(((*QueueBuf)[((*pos)+0)%3] == 0) && ((*QueueBuf)[((*pos)+1)%3] == 0) && ((*QueueBuf)[((*pos)+2)%3] == 0)) {/* (3)寻找 00 00 00 01形式的起始码 */fread(character,1,1,file);(*QueueBuf)[((*pos)++)%3] = *character;if(*character == 1) {//printf("find nal unit 0001 pos = %d\n",pos);return 2;}} else;}return 0;
}/* 寻找h264文本中的rbsp流 */
static int find_nal_unit_data(FILE *file)
{char QueueBuf[3] = {0};char character = 0;int pos = 0;int retVal = 0;while(!feof(file) && !ferror(file)) {/* 寻找nal unit head */retVal = NalUnitOps->find_nal_unit_head(&QueueBuf,&pos,&character,file);if(retVal == 1 || retVal == 2) {/* 判断nal unit type */NalUnitOps->find_nal_unit_type(&QueueBuf,&pos,&character,file);} else if(retVal == 0) {/* 将ebsp流转化为rbsp流,并且输出到终端上显示 */if(NalUnitOps->nal_unit_ebsp_to_rbsp(&QueueBuf,&pos));elseprintf("%c",character);} else;}return 0;
}static int open_file(FILE **file, const char *file_path)
{int Rval = 0;if(!(*file = fopen(file_path,"r"))) {printf("open file failure!\n");Rval = -1; }return Rval;
}static int close_file(FILE *file)
{int Rval = 0;if((Rval = (fclose(file))) != 0) {printf("close file failure!\n");Rval = -1;}return Rval;
}NAL_UNIT_OPS nal_unit_fops = {.find_nal_unit_data = find_nal_unit_data,.find_nal_unit_head = find_nal_unit_head,.find_nal_unit_type = find_nal_unit_type,.nal_unit_ebsp_to_rbsp = nal_unit_ebsp_to_rbsp,
};FILE_OPS file_fops = {.open_file = open_file,.close_file = close_file,
};int main(int argc,char *argv[])
{if(argc != 2) {printf("pleasr input ./elf ./h264_file \n");return -1;}printf("find Nal Unit data\n");FILE *file = NULL;FileOps = &file_fops;NalUnitOps = &nal_unit_fops;FileOps->open_file(&file,argv[1]);/* 寻找nal unit 的rbsp数据流 */NalUnitOps->find_nal_unit_data(file);done:FileOps->close_file(file);return 0;
}