视音频数据处理入门:FLV封装格式解析

跟着雷神学音视频编解码

1,flv文件结构

2,注意

1),结构体的定义:注意这两个结构体一定要是unsigned char的,之前定义成char的,换成int的时候,会出问题。

typedef struct tag_flvHeader
{
	unsigned char		pchSignature[3];
	unsigned char		chVersion;
	unsigned char		chFlag;
	uint32_t 		ui32DataOffset;
}FlvHeader;

typedef struct  tag_TagHeader
{
	unsigned char		chTag;
	unsigned char		chDataSize[3];
	unsigned char		chTimestamp[3];
	uint32_t	Reserved;
}TagHeader;

//reverse_bytes - turn a BigEndian byte array into a LittleEndian integer
int reverse_bytes(unsigned char * p, char c) {
	int r = 0;
	int i;
	for (i = 0; i < c; i++)
		r |= (*(p + i) << (((c - 1) * 8) - 8 * i));
	return r;
}

3,代码

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

//Important!
#pragma pack(1)


#define TAG_TYPE_SCRIPT 18
#define TAG_TYPE_AUDIO  8
#define TAG_TYPE_VIDEO  9

typedef struct tag_flvHeader
{
	unsigned char		pchSignature[3];
	unsigned char		chVersion;
	unsigned char		chFlag;
	uint32_t 		ui32DataOffset;
}FlvHeader;

typedef struct  tag_TagHeader
{
	unsigned char		chTag;
	unsigned char		chDataSize[3];
	unsigned char		chTimestamp[3];
	uint32_t	Reserved;
}TagHeader;

//reverse_bytes - turn a BigEndian byte array into a LittleEndian integer
int reverse_bytes(unsigned char * p, char c) {
	int r = 0;
	int i;
	for (i = 0; i < c; i++)
		r |= (*(p + i) << (((c - 1) * 8) - 8 * i));
	return r;
}

int flv_parser(char* url)
{
	FILE* hInFile = fopen(url, "rb+");
	FILE* hOutFileFlv = NULL;
	FILE* hOutFileMp3 = NULL;
	if (hInFile == NULL)
		return -1;

	FlvHeader flvHeader;
	fread(&flvHeader, 1, sizeof(FlvHeader), hInFile);
	TagHeader tagHeader;

	fseek(hInFile, reverse_bytes((unsigned char*)&flvHeader.ui32DataOffset, sizeof(flvHeader.ui32DataOffset)), SEEK_SET);
	while (!feof(hInFile))
	{
		uint32_t ui32PreviousTagSize = _getw(hInFile);
		int size1 = sizeof(TagHeader);
		fread((void*)&tagHeader, sizeof(TagHeader), 1, hInFile);

		if (feof(hInFile))
			break;

		switch (tagHeader.chTag)
		{
		case TAG_TYPE_AUDIO:
		{
			char tagdata_first_byte;
			tagdata_first_byte = fgetc(hInFile);
			if (hOutFileMp3 == NULL)
				hOutFileMp3 = fopen("myMp3.mp3", "wb");
			uint32_t iTagDataSize = reverse_bytes((unsigned char*)&tagHeader.chDataSize, sizeof(tagHeader.chDataSize))-1;
			for (int i = 0; i < iTagDataSize; i++)
			{
				fputc(fgetc(hInFile), hOutFileMp3);
			}
		}
		break;
		case TAG_TYPE_VIDEO:
		{
  			if (hOutFileFlv == NULL)
			{
 				hOutFileFlv = fopen("myFlv.flv", "wb");
				fwrite(&flvHeader, 1, sizeof(FlvHeader), hOutFileFlv);
				fwrite(&ui32PreviousTagSize, 1, 4, hOutFileFlv);
			}
			fwrite((char*)&tagHeader, 1, sizeof(tagHeader), hOutFileFlv);
			int data_size = reverse_bytes((unsigned char*)&tagHeader.chDataSize, sizeof(tagHeader.chDataSize)) + 4;
			for (int j = 0; j <data_size; j++)
			{
				fputc(fgetc(hInFile), hOutFileFlv);
			}

			fseek(hInFile, -4, SEEK_CUR);
		}
		break;
		default:
		{
			//skip the data of this tag
			fseek(hInFile, reverse_bytes((unsigned char*)&tagHeader.chDataSize, sizeof(tagHeader.chDataSize)), SEEK_CUR);
		}
			break;
		}
	}
	return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值