1. 程式人生 > >C++ 解析H264檔案

C++ 解析H264檔案

#include "stdafx.h"
#include <windows.h>

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"E:\\video\\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];
		memset(btData, 0, dwFileSize);
  
		DWORD dwRead = 0;
		ReadFile(hFile, btData, dwFileSize, &dwRead, NULL);
		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;
}
http://download.csdn.net/detail/sz76211822/9717609