H264 数据avi文件封装和拆解

为了提高H264的保存效率,抛弃了FFmpeg库的avi封装,直接才源码的方式封装avi文件,源码来源于网络,经改造回馈网络。废话不多说,直接上干货。

/*
 * avi_writer.h
 */

#ifndef AVI_UIILS_WRITER_H_
#define AVI_UIILS_WRITER_H_

#ifdef VIDEO_CLIP
#include "video_clip.h"
#endif
typedef unsigned char   uint8_t;
typedef unsigned short  uint16_t;
typedef unsigned   uint32_t;
typedef long long int64_t;

typedef struct avi_idx{
	int  is_key;
	int pos;
	int size;
}AVI_IDX;

typedef struct avi_idx_hwx{
	AVI_IDX idx;
	int serial;
	int64_t st;
}AVI_IDX_HWX;

/////////////////////////////////////////fopen  fp IO ///////////////////////////////////////////////

class avi_writer{
public :
	// open write  低级 io
	avi_writer(float fps,int width,int height);
	// fopen fwrite  高级 io
	avi_writer(int64_t offset,float fps,int width,int height);
	~avi_writer();

private:
	union{
		FILE *fp;
		int fd;
	}_f_handle;

	float _f_fps;
	char  _fcc[4];

	int   _i_width;
	int   _i_height;

	int64_t _i_movi;
	int64_t _i_movi_end;
	int64_t _i_riff;

	int _i_frame;
	int      _i_idx_max;

	AVI_IDX* _idx;
	AVI_IDX_HWX* _idx_hwx;

	char _buff[9];

	int _io_mode;
	int64_t _start_offset;
	int64_t _off_set;

	int _frist_serial;
	int _cur_serial;

	int64_t _frist_st;
	int64_t _cur_st;

private:
	void avi_write_char(char c);
	void avi_write_uint16(uint16_t w);
	void avi_write_uint32(uint32_t dw );
	void avi_write_fourcc(char fcc[4] );
	int avi_write_buff(void* buff,int size);
	int64_t avi_tell();
	int64_t avi_seek(int64_t offset);

	void avi_set_fourcc( void *_p, char fcc[4]);
	void avi_set_dw( void *_p, uint32_t dw );
	void avi_set_dw64( void *_p, int64_t dw );

	void avi_write_header();
	void avi_write_idx();
	void avi_write_idx_hwx();

public :
	int avi_open(const char* filename);
	int write_frame(void *data, int size, int b_key );
#ifdef VIDEO_CLIP
	int avi_write_clip(VideoClip * clip);
#endif
	int64_t get_avi_file_size();
	int64_t avi_close();

public:
	void avi_fflush();
	int get_frist_serial();
	int get_cur_serial();
	int64_t get_frist_st();
	int64_t get_cur_st();
	int get_cur_fream_num();

	//获取当前已经存盘数据的索引区
	int get_cur_idx_hwx(AVI_IDX_HWX* idx,int fream_num);

};

#endif
#ifndef AVI_UTILS_READER_H_
#define AVI_UTILS_READER_H_

typedef long long int64_t;
typedef unsigned char   uint8_t;
typedef unsigned short  uint16_t;
typedef unsigned   uint32_t;

#include "avi_writer.h"

typedef struct
{
	FILE *f;

	char fcc[4];

	float f_fps;

	int i_width;
	int i_height;

	int64_t i_movi;
	int64_t i_movi_end;
	int64_t i_riff;

	int i_frame;
	int i_idx_max;
	uint32_t *idx;
	uint32_t *idx_hwx;
} avi_read_t;

typedef struct avi_idx1_hwx{
	int  is_key;
	int pos;
	int size;
	int serial;
	int64_t st;
}IDX_HWX;

//读取avi标准索引区
int avi_read_avi_idx1(avi_read_t* a,AVI_IDX**idx);

int avi_read_idx_hwx(avi_read_t* a,IDX_HWX** idx);
int avi_read( avi_read_t *a, void *buf,IDX_HWX* idx);

void avi_rd_init( avi_read_t *a, FILE *f, float *f_fps,int *width,int *height);

int avi_read( avi_read_t *a, void *buf, int buf_size, int* b_key );
int avi_read_frame(avi_read_t *a, void *buf, int buf_size,int64_t pos);
void avi_rd_end( avi_read_t * a);

#endif /* AVI_READER_H_ */
/*
 * avi_write.cpp
 *<pre name="code" class="cpp">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "avi_writer.h"
#include "avi_reader.h"

uint16_t avi_read_uint16( avi_read_t *a)
{
	uint16_t dw;

    dw=fgetc(a->f);
	dw|=fgetc(a->f)<<8;

	return dw;
}

uint32_t avi_read_uint32( avi_read_t *a)
{
	uint32_t dw(0);

	unsigned char c = 0;
	c= fgetc(a->f);

	dw |=(c&0x000000ff);
	c = 0;
	c= fgetc(a->f);
	dw |= (c&0x000000ff)<<8;

	c = 0;
	c= fgetc(a->f);
	dw |= (c&0x000000ff)<<16;
	c = 0;
	c= fgetc(a->f);
	dw |= (c&0x000000ff)<<24;
	c = 0;
	/*
	dw = fgetc(a->f);
	dw |= (fgetc(a->f)&0xff)<<8;
	dw |= (fgetc(a->f)&0xff)<<16;
	dw |= (fgetc(a->f)&0xff)<<24;
	*/
	return dw;
}

int64_t avi_read_int64( avi_read_t *a)
{
	int64_t dw;

	dw = (int64_t) fgetc(a->f);
	dw |=(int64_t) (fgetc(a->f)&0xff)<<8;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<16;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<24;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<32;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<40;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<48;
	dw |=(int64_t) (fgetc(a->f)&0xff)<<56;

	return dw;
}

void avi_read_fourcc( avi_read_t *a, char fcc[4] )
{
	fcc[0]=fgetc(a->f);
	fcc[1]=fgetc(a->f);
	fcc[2]=fgetc(a->f);
	fcc[3]=fgetc(a->f);
}

static void avi_red_dw( void *_p, uint32_t dw )
{
    uint8_t *p =(uint8_t *)_p;

    p[0] = ( dw      )&0xff;
    p[1] = ( dw >> 8 )&0xff;
    p[2] = ( dw >> 16)&0xff;
    p[3] = ( dw >> 24)&0xff;
}

static void avi_read_header( avi_read_t *a )
{
	char buf[8];
	unsigned int uint32_data;

    avi_read_fourcc( a, buf );
    a->i_riff = avi_read_uint32( a);
    avi_read_fourcc( a, buf );

    avi_read_fourcc( a, buf );
    uint32_data = avi_read_uint32( a );
    avi_read_fourcc( a, buf );

    avi_read_fourcc( a, buf );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a);
    a->i_frame = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    a->i_width = avi_read_uint32( a );
    a->i_height = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );

    avi_read_fourcc( a, buf );
    uint32_data = avi_read_uint32( a );
    avi_read_fourcc( a, buf );

    avi_read_fourcc( a, buf );
    uint32_data = avi_read_uint32( a );
    avi_read_fourcc( a, buf );
    avi_read_fourcc( a, a->fcc );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    a->f_fps = (float)(avi_read_uint32( a )/1000);
    uint32_data = avi_read_uint32( a );
    a->i_frame = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    a->i_width = avi_read_uint16( a );
    a->i_height = avi_read_uint16( a );

    avi_read_fourcc( a, buf );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    avi_read_uint16( a );
    avi_read_uint16( a );
    avi_read_fourcc( a,  a->fcc );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );
    uint32_data = avi_read_uint32( a );

    avi_read_fourcc( a, buf );
    a->i_movi_end = avi_read_uint32( a ) -4;
    avi_read_fourcc( a, buf );

#if 0
	/* Append idx chunk */
    if( a->i_idx_max <= a->i_frame )
    {
        a->i_idx_max += 1000;
        a->idx =(uint32_t*)realloc(a->idx, a->i_idx_max * 16 );
    }

    memcpy( &a->idx[4*a->i_frame+0], "00dc", 4 );
    avi_set_dw( &a->idx[4*a->i_frame+1], b_key ? AVIIF_KEYFRAME : 0 );
    avi_set_dw( &a->idx[4*a->i_frame+2], i_pos );
    avi_set_dw( &a->idx[4*a->i_frame+3], size );
#endif
}
/*
static void avi_read_idx( avi_read_t *a )
{
	char buf[8];

    avi_read_fourcc( a, buf );
    a->i_frame = avi_read_uint32( a ) / 16;
    //fwrite( a->idx, a->i_frame * 16, 1, a->f );
}*/

//读取avi标准索引区
int avi_read_avi_idx1(avi_read_t* a,AVI_IDX**idx)
{
	char buf[8];
	char* idx_buff = NULL;

	int i_movi_end = a->i_movi_end;

	int idx_pos_start;
	int idx_pos_end;
	int idx_len;
	//int64_t riff = a->i_riff+(56*4-4);
	int64_t temp;

	int ret;
	int frame_num =0;
	int i=0;

	temp=fseek(a->f,i_movi_end,SEEK_SET);

	memset(buf,0,8);
	avi_read_fourcc( a, buf );
	if(strcmp(buf,"idx1"))
	{
		printf("<<<<<<<read buf is not 'idx1'>>>>>read buf is %s\n",buf);
		return -1;
	}

	frame_num = avi_read_uint32(a)/16;

	if(frame_num <=0 )
	{
		*idx = NULL;
		printf("<<<<<<<read frame num faild>>>>>\n");
		return frame_num;
	}

	AVI_IDX* idx_tmp = (AVI_IDX*)calloc(frame_num,sizeof(AVI_IDX));

	for(i=0;i<frame_num;i++)
	{
		memset(buf,0,8);
		avi_read_fourcc( a, buf );
		if(strcasecmp(buf,"00dc"))
		{
			printf("<<<<<<<read idx faild>>>>>\n");
			break;
		}
		idx_tmp[i].is_key=avi_read_uint32(a);
		idx_tmp[i].pos = avi_read_uint32(a);
		idx_tmp[i].size = avi_read_uint32(a);
	}

	if(i!=frame_num)
	{
		free(idx_tmp);
		idx_tmp = NULL;
		return 0;
	}

	*idx = idx_tmp;
	return frame_num;
}

int avi_read_idx_hwx(avi_read_t* a,IDX_HWX** idx)
{
	char buf[8];
	char* idx_buff = NULL;

	int riff = a->i_riff+8;
	int riff2 = a->i_riff;
	int idx_pos_start;
	int idx_pos_end;
	int idx_len;
	//int64_t riff = a->i_riff+(56*4-4);
	int64_t temp;

	int ret;
	int frame_num =0;
	int i=0;

	temp=fseek(a->f,riff,SEEK_SET);

	memset(buf,0,8);
	avi_read_fourcc( a, buf );
	if(strcmp(buf,"ihwx"))
	{
		// Ipnc_DbgPrintf2(_TraceError,"<<<<<<<read buf is not 'ihwx'>>>>>read buf is %s\n",buf);
		return -1;
	}

	idx_pos_start = ftell( a->f );
	fseek(a->f,0,SEEK_END);
	idx_pos_end  = ftell( a->f );

	idx_len  = idx_pos_end - idx_pos_start;
	fseek(a->f,0-idx_len,SEEK_END);

	frame_num = avi_read_uint32(a)/28;

	if(frame_num <=0 )
	{
		*idx = NULL;
		return frame_num;
	}

	IDX_HWX* idx_hwx = (IDX_HWX*)calloc(frame_num,sizeof(IDX_HWX));

	for(i=0;i<frame_num;i++)
	{
		memset(buf,0,8);
		avi_read_fourcc( a, buf );
		if(strcasecmp(buf,"hwx0"))
		{
			break;
		}
		idx_hwx[i].is_key=avi_read_uint32(a);
		idx_hwx[i].pos = avi_read_uint32(a);
		idx_hwx[i].size = avi_read_uint32(a);
		idx_hwx[i].serial = avi_read_uint32(a);
		idx_hwx[i].st =(long long)avi_read_int64(a);
	}

	if(i!=frame_num)
	{
		free(idx_hwx);
		idx_hwx = NULL;
		*idx = NULL;
		return 0;
	}

	*idx = idx_hwx;
	return frame_num;
}

void avi_rd_init( avi_read_t *a, FILE *f, float *f_fps,int *width,int *height)
{
	char hwx_fcc[8];
    a->f = f;
    a->f_fps = 0;
    a->i_width = 0;
    a->i_height = 0;
    a->i_frame = 0;
    a->i_movi = 0;
    a->i_riff = 0;
    a->i_movi_end = 0;
    a->i_idx_max = 0;
    a->idx = NULL;
    a->idx_hwx = NULL;
    avi_read_header( a );
    *f_fps=a->f_fps;
	*width=a->i_width;
	*height=a->i_height;

}

int avi_read( avi_read_t *a, void *buf, int buf_size, int* b_key )
{
	int frame_size = 0;
	int read_size = 0;
    int64_t i_pos = ftell( a->f );
	char fcc[8];
	char c;

	if (!a || !buf || (buf_size<16))
		return 0;

	//avi_read_idx_hwx("ihwx",hwx_fcc);

	if (b_key) *b_key = 0;
	while ((frame_size<=0) && (!feof(a->f)))
	{
		avi_read_fourcc( a,  fcc);//
		fcc[4] = '\0';
		if (!strcmp(fcc, "00dc"))
		{
			frame_size = avi_read_uint32( a );
			if ((frame_size>16) && (frame_size<buf_size))
			{
				read_size = fread( buf, 1, frame_size, a->f );
				if (read_size == frame_size)
				{
					if (frame_size&0x01 )
						c = fgetc( a->f );/* pad */

					a->i_frame++;
				}
			}
		}
	}

	return frame_size;
}

/*
 * sucess return frame_size
 * faild  return -1
 */
int avi_read_frame(avi_read_t *a, void *buf, int buf_size,int64_t pos)
{
	int frame_size = 0;
	int read_size = 0;
	char fcc[8];
	char c;
	int64_t i_pos = ftell( a->f );

	if (!a || !buf || (buf_size<16))
		return -1;

	if(i_pos!=pos)
		fseek(a->f,pos,SEEK_SET);

	avi_read_fourcc( a,  fcc);//
	fcc[4] = '\0';
	if (!strcmp(fcc, "00dc"))
	{
		frame_size = avi_read_uint32( a );
		if ((frame_size>16) && (frame_size<buf_size))
		{
			read_size = fread( buf, 1, frame_size, a->f );
			if (read_size == frame_size)
			{
				if (frame_size&0x01 )
					c = fgetc( a->f );/* pad */
			}
			else
			{
				return -1;
			}
		}
	}
	else
	{
		return -1;
	}

	return frame_size;
}

void avi_rd_end( avi_read_t * a)
{

}
/*
 * avi_write.cpp
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "avi_writer.h"

#ifdef WIN32
#include "..\..\..\media_base\media_dbg.h"
#include "..\..\..\media_base\sync.h"
#else
#include "sync.h"

#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
#endif

/* Flags in avih */
#define AVIF_HASINDEX       0x00000010  // Index at end of file?
#define AVIF_ISINTERLEAVED  0x00000100
#define AVIF_TRUSTCKTYPE    0x00000800  // Use CKType to find key frames?

#define AVIIF_KEYFRAME      0x00000010L /* this frame is a key frame.*/

avi_writer::avi_writer(int64_t offset,float fps,int width,int height)
{
	_i_width = width;
	_i_height = height;
	_f_fps = fps;

	memcpy( _fcc,"h264",4);
	_i_width = width;
	_i_height = height;
	_i_frame = 0;
	_i_movi = 0;
	_i_riff = 0;
	_i_movi_end = 0;
	_i_idx_max = 0;
	_idx = NULL;
	_idx_hwx = NULL;

	_io_mode = 0; // open write
	_start_offset = offset;
	_off_set = 0;

	_frist_serial=0;
	_cur_serial=0;

	_frist_st=0;
	_cur_st=0;
}

avi_writer::avi_writer(float fps,int width,int height)
{
	_i_width = width;
	_i_height = height;
	_f_fps = fps;

	memcpy( _fcc,"h264",4);
	_i_width = width;
	_i_height = height;
	_i_frame = 0;
	_i_movi = 0;
	_i_riff = 0;
	_i_movi_end = 0;
	_i_idx_max = 0;
	_idx = NULL;
	_idx_hwx = NULL;

	_io_mode = 1;  // fopen fwrite
	_start_offset = 0;
	_off_set = 0;

	_frist_serial=0;
	_cur_serial=0;

	_frist_st=0;
	_cur_st=0;
}

avi_writer::~avi_writer()
{
	if(_idx)
		free(_idx);
	_idx = NULL;
	if(_idx_hwx)
		 free(_idx_hwx);
	_idx_hwx = NULL;
}

void avi_writer::avi_write_char(char c)
{
	if(_io_mode)
	{
		fputc( c, _f_handle.fp);
	}
	else
	{
		write(_f_handle.fd,&c,1);
	}
	_off_set += 1l;

}

void avi_writer::avi_write_uint16(uint16_t w)
{
	if(_io_mode)
	{
		fputc( ( w      ) & 0xff, _f_handle.fp);
		fputc( ( w >> 8 ) & 0xff, _f_handle.fp );
	}
	else
	{
		_buff[0] = ( w      ) & 0xff;
		_buff[1] = ( w >> 8 ) & 0xff;
		_buff[2] = '\0';
		write(_f_handle.fd,_buff,2);
	}

	_off_set += 2l;
}
void avi_writer::avi_write_uint32(uint32_t dw )
{
	if(_io_mode)
	{
		fputc( ( dw      ) & 0xff,_f_handle.fp );
		fputc( ( dw >> 8 ) & 0xff,_f_handle.fp);
		fputc( ( dw >> 16) & 0xff,_f_handle.fp );
		fputc( ( dw >> 24) & 0xff,_f_handle.fp);
	}
	else
	{
		_buff[0] = ( dw       ) & 0xff;
		_buff[1] = ( dw >> 8  ) & 0xff;
		_buff[2] = ( dw >> 16 ) & 0xff;
		_buff[3] = ( dw >> 24 ) & 0xff;
		_buff[4] = '\0';

		write(_f_handle.fd,_buff,4);
	}
	_off_set += 4l;
}
void avi_writer::avi_write_fourcc(char fcc[4] )
{
	if(_io_mode)
	{
		fputc( fcc[0],_f_handle.fp);
		fputc( fcc[1],_f_handle.fp);
		fputc( fcc[2],_f_handle.fp);
		fputc( fcc[3],_f_handle.fp);
	}
	else
	{
		write(_f_handle.fd,fcc,4);
	}
	_off_set += 4l;
}

int avi_writer::avi_write_buff(void* buff,int size)
{
	int ret=0;

	if(_io_mode)
	{
		ret = fwrite(buff,1,size,_f_handle.fp);
	}
	else
	{
		ret = write(_f_handle.fd,buff,size);
	}

	if(ret!=size)
	{
		Ipnc_DbgPrintf2(_TraceInfo, "write error\n");
	}

	_off_set +=(int64_t)ret;

	return ret;
}

void avi_writer::avi_write_header()
{
	 avi_write_fourcc("RIFF" );
	avi_write_uint32(_i_riff > 0 ? _i_riff - 8 : 0xFFFFFFFF );
	avi_write_fourcc("AVI " );

	avi_write_fourcc("LIST" );
	avi_write_uint32( 4 + 4*16 + 12 + 4*16 + 4*12 );
	avi_write_fourcc("hdrl" );

	avi_write_fourcc("avih" );
	avi_write_uint32(4*16 - 8 );
	avi_write_uint32(1000000 / _f_fps );
	avi_write_uint32(0xffffffff );
	avi_write_uint32(0 );
	avi_write_uint32(AVIF_HASINDEX|AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE);
	avi_write_uint32(_i_frame );
	avi_write_uint32(0 );
	avi_write_uint32(1 );
	avi_write_uint32(1000000 );
	avi_write_uint32(_i_width );
	avi_write_uint32(_i_height );
	avi_write_uint32(0 );
	avi_write_uint32(0 );
	avi_write_uint32(0 );
	avi_write_uint32(0 );

	avi_write_fourcc("LIST" );
	avi_write_uint32( 4 + 4*16 + 4*12 );
	avi_write_fourcc("strl" );

	avi_write_fourcc("strh" );
	avi_write_uint32( 4*16 - 8 );
	avi_write_fourcc("vids" );
	avi_write_fourcc(_fcc );
	avi_write_uint32(0 );
	avi_write_uint32(0 );
	avi_write_uint32(0 );
	avi_write_uint32(1000 );
	avi_write_uint32(_f_fps * 1000 );
	avi_write_uint32(0 );
	avi_write_uint32(_i_frame );
	avi_write_uint32(1024*1024 );
	avi_write_uint32(-1 );
	avi_write_uint32(_i_width * _i_height );
	avi_write_uint32(0 );
	avi_write_uint16(_i_width );
	avi_write_uint16(_i_height );

	avi_write_fourcc("strf" );
	avi_write_uint32( 4*12 - 8 );
	avi_write_uint32( 4*12 - 8 );
	avi_write_uint32( _i_width );
	avi_write_uint32( _i_height );
	avi_write_uint16( 1 );
	avi_write_uint16( 24 );
	avi_write_fourcc( _fcc );
	avi_write_uint32(_i_width * _i_height );
	avi_write_uint32( 0 );
	avi_write_uint32( 0 );
	avi_write_uint32( 0 );
	avi_write_uint32( 0 );

	avi_write_fourcc("LIST" );
	avi_write_uint32( _i_movi_end > 0 ? _i_movi_end - _i_movi + 4: 0xFFFFFFFF );
	avi_write_fourcc("movi" );
}

void avi_writer::avi_set_fourcc( void *_p, char fcc[4] )
{
	uint8_t *p =(uint8_t *)_p;
	p[0] = fcc[0];
	p[1] = fcc[1];
	p[2] = fcc[2];
	p[3] = fcc[3];
}
void avi_writer::avi_set_dw( void *_p, uint32_t dw )
{
	uint8_t *p =(uint8_t *)_p;

	p[0] = ( dw      )&0xff;
	p[1] = ( dw >> 8 )&0xff;
	p[2] = ( dw >> 16)&0xff;
	p[3] = ( dw >> 24)&0xff;
}
void avi_writer::avi_set_dw64( void *_p, int64_t dw )
{
	uint8_t *p =(uint8_t *)_p;

	p[0] = ( dw      )&0xff;
	p[1] = ( dw >> 8 )&0xff;
	p[2] = ( dw >> 16)&0xff;
	p[3] = ( dw >> 24)&0xff;
	p[4] = ( dw >> 32)&0xff;
	p[5] = ( dw >> 40)&0xff;
	p[6] = ( dw >> 48)&0xff;
	p[7] = ( dw >> 56)&0xff;
}

int64_t avi_writer::avi_tell()
{
	int64_t pos = 0;

	if(_io_mode)
	{
		pos =(int64_t)ftell(_f_handle.fp);
	}
	else
	{
		pos = _off_set;
	}

	return pos;
}

int64_t avi_writer::avi_seek(int64_t offset )
{
	if(_io_mode)
		fseek(_f_handle.fp, offset, SEEK_SET);
	else
		lseek64(_f_handle.fd,_start_offset+offset,SEEK_SET);
}

void avi_writer::avi_write_idx()
{
	int i=0;
	uint32_t* buff = NULL;

	avi_write_fourcc("idx1" );
	avi_write_uint32(_i_frame * 16 );

	buff = (uint32_t*)calloc(sizeof(uint32_t),_i_frame*16);
	if(!buff)
	{
		Ipnc_DbgPrintf2(_TraceInfo, "no mem....\n");
		return ;
	}

	for(i=0;i<_i_frame;i++)
	{
		avi_set_fourcc(&buff[4*i+0],"00dc");
		avi_set_dw(&buff[4*i+1], _idx[i].is_key);
		avi_set_dw(&buff[4*i+2], _idx[i].pos );
		avi_set_dw(&buff[4*i+3], _idx[i].size );
	}
	avi_write_buff(buff,sizeof(uint32_t)*_i_frame * 16);
	free(buff);
	free(_idx);
	_idx  = NULL;
}
void avi_writer::avi_write_idx_hwx()
{
	int i=0;
	uint32_t* buff = NULL;

	if(!_idx_hwx)
		return;

	avi_write_fourcc("ihwx");
	avi_write_uint32(_i_frame);

	buff = (uint32_t*)calloc(sizeof(uint32_t),_i_frame*28);
	if(!buff)
	{
		Ipnc_DbgPrintf2(_TraceInfo, "no mem....\n");
		return ;
	}

	Ipnc_DbgPrintf2(_TraceInfo, "frist serial:%d end serial:%d frist st:%lld cur st:%lld\n",
		_frist_serial,_cur_serial,_frist_st,_cur_st);

	for(i=0;i<_i_frame;i++)
	{
		avi_set_fourcc(&buff[7*i+0],"hwx0");
		avi_set_dw(&buff[7*i+1], _idx_hwx[i].idx.is_key);
		avi_set_dw(&buff[7*i+2], _idx_hwx[i].idx.pos );
		avi_set_dw(&buff[7*i+3], _idx_hwx[i].idx.size );
		avi_set_dw(&buff[7*i+4], _idx_hwx[i].serial);
		avi_set_dw64(&buff[7*i+5], _idx_hwx[i].st);
	}
	avi_write_buff(buff,sizeof(uint32_t)*_i_frame*28);

	free(buff);
	free(_idx_hwx);
	_idx_hwx = NULL;
}

int avi_writer::avi_open(const char* filename)
{
	if(!filename)
	{
		Ipnc_DbgPrintf2(_TraceError, "invalid filename\n");
		return -1;
	}

	if(_io_mode)
	{
		_f_handle.fp = fopen(filename,"wb+");
		if(!_f_handle.fp)
		{
			Ipnc_DbgPrintf2(_TraceError,
					"create avi file failed 1: error=%d, file=%s!!!\n",
					errno, filename);
			return -1;
		}
	}
	else
	{
		_f_handle.fd = open(filename,O_CREAT|O_RDWR);
		if(_f_handle.fd < 0 )
		{
			Ipnc_DbgPrintf2(_TraceError,
						"create avi file failed 2: error=%d, file=%s!!!\n",
						errno, filename);
			return -1;
		}
	}

	Ipnc_DbgPrintf2(_TraceError,
			"create avi file success: %s\n",
			filename);
	avi_seek(0);
	avi_write_header();
	return 0;
}
int avi_writer::write_frame(void *data, int size, int b_key )
{
	int ret=0;
	int64_t i_pos = avi_tell();

	/* chunk header */
	avi_write_fourcc("00dc" );
	avi_write_uint32(size);

	ret = avi_write_buff(data,size);

	if(size&0x01 )
	{
		/* pad */
		avi_write_char(0);
	}

	/* Append idx chunk */
	if( _i_idx_max <= _i_frame )
	{
		_i_idx_max += 1000;
		_idx =(AVI_IDX*)realloc(_idx,_i_idx_max*sizeof(AVI_IDX));
	}
	_idx[_i_frame].is_key = b_key ? AVIIF_KEYFRAME : 0 ;
	_idx[_i_frame].pos = i_pos;
	_idx[_i_frame].size = size;

	_i_frame++;

	return ret;
}
#ifdef VIDEO_CLIP
int avi_writer::avi_write_clip(VideoClip * clip)
{
	int ret=0;
	int j=0,size=0,serial=0;
	int64_t timest=0;
	int is_key=0;

	int64_t i_pos = avi_tell();

	//Ipnc_DbgPrintf2(_TraceInfo, "write clip pos:%lld offset:%lld\n",i_pos,_off_set);

	/* chunk header */
	ret = avi_write_buff( clip->get_buff_head(),clip->size());
/*
	Ipnc_DbgPrintf2(_TraceInfo, "clip frame num:%d start: serial:%d st:%lld end serial:%d st:%lld\n",
			clip->frame_count(),
			clip->get_frame_serial(0),
			clip->get_frame_timest(0),
			clip->get_frame_serial(clip->frame_count()-1),
			clip->get_frame_timest(clip->frame_count()-1));
	Ipnc_DbgPrintf2(_TraceInfo, "avi file frame num :%d\n",_i_frame);
*/
	for (j=0; j<clip->frame_count(); j++)
	{
		/* Append idx chunk */
		if( _i_idx_max <= _i_frame )
		{
			_i_idx_max += 1000;
			_idx =(AVI_IDX*)realloc(_idx,_i_idx_max*sizeof(AVI_IDX));
			_idx_hwx =(AVI_IDX_HWX*)realloc(_idx_hwx, _i_idx_max * sizeof(AVI_IDX_HWX));
		}

		is_key = clip->get_frame_key(j);
		size = clip->get_frame_size(j);
		serial = clip->get_frame_serial(j);
		timest = clip->get_frame_timest(j);

		if(!_frist_serial)
			_frist_serial=serial;
		_cur_serial=serial;
		if(!_frist_st)
			_frist_st=timest;
		_cur_st=timest;

		_idx[_i_frame].is_key = is_key ? AVIIF_KEYFRAME : 0 ;
		_idx[_i_frame].pos = i_pos;
		_idx[_i_frame].size = size;

		_idx_hwx[_i_frame].idx.is_key = is_key ? AVIIF_KEYFRAME : 0 ;
		_idx_hwx[_i_frame].idx.pos = i_pos;
		_idx_hwx[_i_frame].idx.size = size;
		_idx_hwx[_i_frame].serial = serial;
		_idx_hwx[_i_frame].st = timest;

		i_pos += (size+8+(size&0x01));

		_i_frame++;
	}

	return ret;
}
#endif
int64_t avi_writer::avi_close()
{
	int64_t file_size = 0;
	_i_movi_end = avi_tell();

	/* write index */
	avi_write_idx();

	_i_riff = avi_tell();
	//Ipnc_DbgPrintf2(_TraceInfo, "avi end:%lld offset:%lld\n",_i_riff,_off_set);
	//idx hwx
	//avi_write_idx_hwx();

	file_size = avi_tell();
	//Ipnc_DbgPrintf2(_TraceInfo, "avi file len :%lld offset:%lld\n",file_size,_off_set);
	/* Fix header */
	avi_seek(0);
	avi_write_header();

	if(_io_mode)
	{
		fclose(_f_handle.fp);
		_f_handle.fp = NULL;
	}
	else
	{
		close(_f_handle.fd);
		_f_handle.fd = 0;
	}

	return file_size;
}

int64_t avi_writer::get_avi_file_size()
{
	return _off_set;
}

void avi_writer::avi_fflush()
{
	if(_io_mode)
	{
		fflush(_f_handle.fp);
	}
}

int avi_writer::get_frist_serial()
{
	return _frist_serial;
}
int avi_writer::get_cur_serial()
{
	return _cur_serial;
}
int64_t avi_writer::get_frist_st()
{
	return _frist_st;
}
int64_t avi_writer::get_cur_st()
{
	return _cur_st;
}
int avi_writer::get_cur_fream_num()
{
	return _i_frame;
}
int avi_writer::get_cur_idx_hwx(AVI_IDX_HWX* idx,int fream_num)
{
	if(fream_num <=0 || !idx)
	{
		Ipnc_DbgPrintf2(_TraceInfo,"invalid idx or frame num.....\n");
		return -1;
	}
	if(!_idx_hwx)
	{
		Ipnc_DbgPrintf2(_TraceInfo,"invalid _idx_hwx.....\n");
		return -1;
	}
	memcpy(idx,_idx_hwx,fream_num* sizeof(AVI_IDX_HWX));
	return 0;
}
时间: 2024-11-09 09:36:01

H264 数据avi文件封装和拆解的相关文章

【C#】AviFile使用(播放AVI文件,兼容性比较差)

最近在做一个视频识别项目,需要用到视频处理,在codeproject上找到了一个关于对Avi的操作库,感觉不错,在这里把一些要点记录下来 http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library Avi视频文件的编码有很多,这个库只支持部分Avi文件,有些Avi文件不支持,具体哪些不支持还没搞清楚 AviFile库提供了 1.从视频流中图片的处理 2.视频中音频的处理 3.压缩和解压视频

(转)从海康7816的ps流里获取数据h264数据

海康7816使用ps流来封装h.264数据,这里使用的解码器无法识别ps流,因此需要将h264数据从ps流里提取出来 对于ps流的规定可以参考13818-1文档 这里从7816里获取到一些数据取样 00 00 01 BA 44 73 26 B8 34 01 00 00 03 FE FF FF 00 00 00 0100 00 01 BC00 5A E0 FF 00 24 40 0E 48 4B 00 01 0D AF C5 D3 E0 07 FF FF FF FF 41 12 48 4B 00

H264 NALU 使用PS封装 RTP发送

最近由于项目平台需求,要将H264 NALU封装为PS再用RTP发送,PS封装按照ISO DEC-13818-1标准.一个PS包包含PS Header, PES Header, PS system header, PS system map等. 针对H264做如下PS封装: 1.每个IDR NALU前一般都会包含SPS.PPS等NALU,因此将SPS.PPS.IDR 的NALU封装为一个PS包,包括ps头,然后加上PS system header,PS system map,PES header

Node-mongodb链接数据库函数的封装

代码如下: 创建Database.js文件放到单独目录下,这里取名为model. /** * Created by pi on 2016/9/5. */ function openDatabase(databaseName,collectionName,fn){ var mongoClient=require('mongodb').MongoClient; var DB_STR="mongodb://localhost:27017/"+databaseName; mongoClient

.264视频文件封装成.MP4方法

.264视频文件封装成.MP4方法 需求: 海康威视输出的视频格式为.264格式,而html5端对其不支持,所以需要将其封装成. mp4格式. Tips:我们常常提到的. mp4格式视频,其实指的是一种容器(或者说集合体),包括视频.音频,甚至是字幕等.而.264是指一种视频的编码方式,起压缩作用.所以将.264文件转换成.mp4文件,其实就是一个解码的过程. 思路: 网上已经提供解决方案,采用ffmpeg库,先将.264文件解码,再编码生成.mp4文件,但这种方式效率较低,10M的视频可能需要

ffmpeg+libx264+facc交叉编译 实现264流录制avi文件

默认交叉编译器已经搭建好............... 需求: 把标准的h264流保存成avi格式的实现文件,所以需要h264的解码器,avi文件容器,传输协议类型是文件,这些会体现在ffmpeg的configure配置上--disable-everything --enable-protocol=file --enable-encoder=libx264 --enable-encoder=libfaac --enable-libx264 --enable-gpl --enable-libfaa

Android数据存储-文件操作

一.预备知识 1.Android中的MVC设计模式 MVC (Model-View-Controller):M是指逻辑模型,V是指视图模型,C则是控制器.一个逻辑模型可以对于多种视图模型,比如一批统计数据你可以分别用柱状图.饼图来表示.一种视图模型也可以对于多种逻辑模型.使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新,这与<设计模式>中的观察者模式是完全一样. MVC好处:从用户的角度出发,用户可

vc++实现avi文件的操作

为了对avi进行读写,微软提供了一套API,总共50个函数,他们的用途主要有两类,一个是avi文件的操作,一类是数据流streams的操作. 1.打开和关闭文件 AVIFileOpen ,AVIFileAddRef, AVIFileRelease 2.从文件中读取文件信息 通过AVIFileInfo可以获取avi文件的一些信息,这个函数返回一个AVIFILEINFO结构,通过AVIFileReadData可以用来获取AVIFileInfo函数得不到的信息.这些信息也许不包含在文件的头部,比如拥有

android上传图片并附带上传数据,文件流

关于android的图片上传有两种方式,一种是以文件流的方式上传,图片转换成二进制上穿.另一种是把图片转成base64方式上传,这篇博客我只介绍文件流,关于base64方式会在下一篇博客中介绍! 首先是安卓端:图片上传我们需要一个图片的路径,同过调用本地相册或者拍照可以返回图片路径,这个在这里就不说了:假设我们获得图片路径为PicPath; 下面是安卓代码: 首先我们要封装要发送的数据 数据封装好了以后用String path=URLEncodedUtils.format(Parameters,