从flv格式中分离出裸h264

本身测试能够用,原文连接http://blog.163.com/zhujiatc@126/blog/static/18346382013413112230525/

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

#define HTON16(x)  ((x>>8&0xff)|(x<<8&0xff00))
#define HTON24(x)  ((x>>16&0xff)|(x<<16&0xff0000)|x&0xff00)
#define HTON32(x)  ((x>>24&0xff)|(x>>8&0xff00)|\
	(x << 8 & 0xff0000) | (x << 24 & 0xff000000))

#define STR(x) (x.c_str())
#define FCUR(x) (ftell(x))
#define FSEEK(x,f) (fseek(f,x,SEEK_CUR))
#define FSET(x,f) (fseek(f,x,SEEK_SET))
//#define LOG(x,f) (fprintf(f,STR(x)))
FILE *flvfile = NULL;
FILE *h264file = NULL;

unsigned int size;
bool Init();
void Clear();

bool Read8(int &i8, FILE*f);
bool Read16(int &i16, FILE*f);
bool Read24(int &i24, FILE*f);
bool Read32(int &i32, FILE*f);
bool ReadTime(int &itime, FILE*f);

bool Peek8(int &i8, FILE*f);

bool ReadHead();
void ReadBody();


char flvfilename[256] = { 0 };
char h264filename[256] = { 0 };
bool hasname = false;
int main(int argc, char**argv)
{
	strncpy(flvfilename, "savename.flv", sizeof(flvfilename));
	strncpy(h264filename, "savename.h264", sizeof(h264filename));
	hasname = true;

	if (!Init())
	{
		cout << "Init Err" << endl;
		return -1;
	}
	if (!ReadHead())
	{
		cout << "ReadHead Err" << endl;
		return -1;
	}
	ReadBody();
	cout << "read over" << endl;
	Clear();
	return 0;
}
bool Init()
{
	flvfile = fopen(flvfilename, "rb");
	h264file = fopen(h264filename, "wb");
	if (flvfile == NULL || h264file == NULL)
	{
		return false;
	}
	fseek(flvfile, 0, SEEK_END);
	size = FCUR(flvfile);
	fseek(flvfile, 0, SEEK_SET);
	return true;
}
void Clear()
{
	fclose(flvfile);
	fclose(h264file);
}


bool Read8(int &i8, FILE*f)
{
	if (fread(&i8, 1, 1, f) != 1)
		return false;
	return true;
}
bool Read16(int &i16, FILE*f)
{
	if (fread(&i16, 2, 1, f) != 1)
		return false;
	i16 = HTON16(i16);
	return true;
}
bool Read24(int &i24, FILE*f)
{
	if (fread(&i24, 3, 1, f) != 1)
		return false;
	i24 = HTON24(i24);
	return true;
}
bool Read32(int &i32, FILE*f)
{
	if (fread(&i32, 4, 1, f) != 1)
		return false;
	i32 = HTON32(i32);
	return true;
}
bool Peek8(int &i8, FILE*f)
{
	if (fread(&i8, 1, 1, f) != 1)
		return false;
	fseek(f, -1, SEEK_CUR);
	return true;
}

bool ReadTime(int &itime, FILE*f)
{
	int temp = 0;
	if (fread(&temp, 4, 1, f) != 1)
		return false;
	itime = HTON24(temp);
	itime |= (temp & 0xff000000);
	return true;
}

bool ReadHead()
{
	int headlength = 0;
	int filetype = 0;
	if (!Read24(filetype, flvfile))
		return false;
	int typel = 'flv';
	int typeh = 'FLV';
	if (filetype != typeh&&filetype != typel)
	{
		printf("not flv file\n");
		return false;
	}
	FSEEK(2, flvfile);
	if (!Read32(headlength, flvfile))
		return false;
	printf("headlength:%d\n", headlength);
	/////////跳过头部长度/////
	fseek(flvfile, 0, SEEK_SET);
	FSEEK(headlength, flvfile);
	return true;
}

void H264JIEXI(int datelength);
void ReadBody()
{

	while (true)
	{
		FSEEK(4, flvfile);
		int type = 0;
		int time = 0;
		int htime = 0;
		int datelength = 0;
		int info = 0;

		char buff[256] = { 0 };
		if (!Read8(type, flvfile))
			break;
		if (!Read24(datelength, flvfile))
			break;
		if (!ReadTime(time, flvfile))
			break;
		////////跳过StreamID/////
		FSEEK(3, flvfile);
		if (!Peek8(info, flvfile))
			break;

		int pos = FCUR(flvfile);
		if (type == 9)
			H264JIEXI(datelength);
		FSET(pos + datelength, flvfile);
	}
}

int h264space = 0x01000000;//H264内容间隔标识00000001

void H264JIEXI(int datelength)//关键
{
	int info = 0;
	Read8(info, flvfile);
	int avctype = 0;
	Read8(avctype, flvfile);
	FSEEK(3, flvfile);
	int templength = 0;
	char*tempbuff = NULL;
	if (avctype == 0)
	{
		FSEEK(6, flvfile);

		Read16(templength, flvfile);
		printf("sssize:%d\n", templength);

		tempbuff = (char*)malloc(templength);
		fread(tempbuff, 1, templength, flvfile);
		fwrite(&h264space, 1, 4, h264file);
		fwrite(tempbuff, 1, templength, h264file);
		free(tempbuff);

		Read8(templength, flvfile);//ppsnum

		Read16(templength, flvfile);//ppssize
		printf("ppsize:%d\n", templength);

		tempbuff = (char*)malloc(templength);
		fread(tempbuff, 1, templength, flvfile);
		fwrite(&h264space, 1, 4, h264file);
		fwrite(tempbuff, 1, templength, h264file);
		free(tempbuff);
	}
	else
	{
		//	Read32(templength,flvfile);
		//	tempbuff=(char*)malloc(templength);
		//	fread(tempbuff,1,templength,flvfile);
		//	fwrite(&h264space,1,4,h264file);
		//	fwrite(tempbuff,1,templength,h264file);
		//	free(tempbuff);
		//可能存在多个nal,需所有读取
		int countsize = 2 + 3;
		while (countsize<datelength)
		{
			Read32(templength, flvfile);
			tempbuff = (char*)malloc(templength);
			fread(tempbuff, 1, templength, flvfile);
			fwrite(&h264space, 1, 4, h264file);
			fwrite(tempbuff, 1, templength, h264file);
			free(tempbuff);
			countsize += (templength + 4);
		}
	}
}