C++实现H264文件解析

  • 此文件用于演示如何使用C++解析H264文件,便于刚入门音视频的朋友学习,建议参考协议学习!
//#include "stdafx.h"
#include 
#include 
#include 
#include 

typedef enum {
	NALU_TYPE_SLICE = 1,
	NALU_TYPE_DPA = 2,
	NALU_TYPE_DPB = 3,
	NALU_TYPE_DPC = 4,
	NALU_TYPE_IDR = 5,
	NALU_TYPE_SEI = 6,
	NALU_TYPE_SPS = 7,
	NALU_TYPE_PPS = 8,
	NALU_TYPE_AUD = 9,
	NALU_TYPE_EOSEQ = 10,
	NALU_TYPE_EOSTREAM = 11,
	NALU_TYPE_FILL = 12,
} NaluType;

typedef enum {
	NALU_PRIORITY_DISPOSABLE = 0,
	NALU_PRIRITY_LOW = 1,
	NALU_PRIORITY_HIGH = 2,
	NALU_PRIORITY_HIGHEST = 3
} NaluPriority;

void printfH264(int j, int i, int nLen, int nFrameType)
{
	printf("%d %d", j, i);
	int nForbiddenBit = (nFrameType >> 7) & 0x1;//第1位禁止位,值为1表示语法出错
	int nReference_idc = (nFrameType >> 5) & 0x03;//第2~3位为参考级别
	int nType = nFrameType & 0x1f;//第4~8为是nal单元类型

	printf("  ");
	switch (nReference_idc) {
	case NALU_PRIORITY_DISPOSABLE:
		printf("DISPOS");
		break;
	case NALU_PRIRITY_LOW:
		printf("LOW");
		break;
	case NALU_PRIORITY_HIGH:
		printf("HIGH");
		break;
	case NALU_PRIORITY_HIGHEST:
		printf("HIGHEST");
		break;
	}

	printf("  ");
	switch (nType) {
	case NALU_TYPE_SLICE:
		printf("SLICE");
		break;
	case NALU_TYPE_DPA:
		printf("DPA");
		break;
	case NALU_TYPE_DPB:
		printf("DPB");
		break;
	case NALU_TYPE_DPC:
		printf("DPC");
		break;
	case NALU_TYPE_IDR:
		printf("IDR");
		break;
	case NALU_TYPE_SEI:
		printf("SEI");
		break;
	case NALU_TYPE_SPS:
		printf("SPS");
		break;
	case NALU_TYPE_PPS:
		printf("PPS");
		break;
	case NALU_TYPE_AUD:
		printf("AUD");
		break;
	case NALU_TYPE_EOSEQ:
		printf("EOSEQ");
		break;
	case NALU_TYPE_EOSTREAM:
		printf("EOSTREAM");
		break;
	case NALU_TYPE_FILL:
		printf("FILL");
		break;
	}

	printf("  %d\r\n", nLen);
}

int GetLen(int nPos, int nTotalSize, BYTE* btData)
{
	int nStart = nPos;
	while (nStart < nTotalSize) {
		if (btData[nStart] == 0x00 && btData[nStart + 1] == 0x00 && btData[nStart + 2] == 0x01) {
			return nStart - nPos;
		}
		else if (btData[nStart] == 0x00 && btData[nStart + 1] == 0x00 && btData[nStart + 2] == 0x00 && btData[nStart + 3] == 0x01) {
			return nStart - nPos;
		}
		else {
			nStart++;
		}
	}
	return nTotalSize - nPos;//最后一帧。
}

int _tmain(int argc, _TCHAR* argv[])
{
	BYTE *btData = NULL;
	DWORD dwFileSize = 0;
	HANDLE hFile = CreateFile(L"./sintel.h264", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE) {
		dwFileSize = GetFileSize(hFile, NULL);  //获取文件的大小
		btData = new BYTE[dwFileSize];  //new一个文件大小的buffer
		memset(btData, 0, dwFileSize);

		DWORD dwRead = 0;
		ReadFile(hFile, btData, dwFileSize, &dwRead, NULL);  //将文件中的数据读到创建的buffer中
		CloseHandle(hFile);
	}

	int j = 0;//多少帧
	int i = 0;//偏移量
	while (i < dwFileSize - 4) {
		if (btData[i] == 0x00 && btData[i + 1] == 0x00 && btData[i + 2] == 0x01) {
			int nLen = GetLen(i + 3, dwFileSize, btData);
			printfH264(j, i, nLen, btData[i + 3]);
			j++;
			i += 3;
		}
		else if (btData[i] == 0x00 && btData[i + 1] == 0x00 && btData[i + 2] == 0x00 && btData[i + 3] == 0x01) {
			int nLen = GetLen(i + 4, dwFileSize, btData);
			printfH264(j, i, nLen, btData[i + 4]);
			j++;
			i += 4;
		}
		else {
			i++;
		}
	}

	if (btData) {
		delete[] btData;
	}
	return 0;
}

演示结果:
C++实现H264文件解析_第1张图片

你可能感兴趣的:(音视频)