H264 数据avi文件封装和拆解
2016-05-23 00:13
375 查看
from: http://blog.csdn.net/zhujinghao_09/article/details/44458245
为了提高H264的保存效率,抛弃了FFmpeg库的avi封装,直接才源码的方式封装avi文件,源码来源于网络,经改造回馈网络。废话不多说,直接上干货。
[cpp]
view plain
copy
print?
/*
* 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
[cpp]
view plain
copy
print?
#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_ */
[cpp]
view plain
copy
print?
/*
* 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)
{
}
[cpp]
view plain
copy
print?
/*
* 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;
}
为了提高H264的保存效率,抛弃了FFmpeg库的avi封装,直接才源码的方式封装avi文件,源码来源于网络,经改造回馈网络。废话不多说,直接上干货。
[cpp]
view plain
copy
print?
/*
* 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
[cpp]
view plain
copy
print?
#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_ */
[cpp]
view plain
copy
print?
/*
* 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)
{
}
[cpp]
view plain
copy
print?
/*
* 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;
}
相关文章推荐
- ThreadPoolExecutor里面4种拒绝策略(详细)
- Spring-data-redis:特性与实例
- 什么时候使用覆盖操作
- 正则表达式——肯定环视模拟固化分组
- #pragma_pack(n)_与__attribute(aligned(n))的关系与区别
- 享元模式
- Spark 定制版:006~Spark Streaming源码解读之Job动态生成和深度思考
- 继承,继承的好处
- struts-2小练习
- 2286: [Sdoi2011消耗战
- 工作队列
- 兄台息怒,关于arguments,您的想法和大神是一样一样的----闲聊JS中的apply和call
- android 简单的网格布局 GridLayout
- leetcode_c++:Combination Sum_2(040)
- Untiy3D的粒子系统介绍
- [Java] 作业6(字符串)
- Linux08--Shell程序设计03 shell script
- cqoi2016
- ActionBar 用法
- 字父类中,成员特点体现