📄 avilib.c
字号:
}
/* idx_type remains 0 if neither of the two tests above succeeds */
}
if(idx_type == 0)
{
/* we must search through the file to get the index */
lseek(AVI->fdes, AVI->movi_start, SEEK_SET);
AVI->n_idx = 0;
while(1)
{
if( read(AVI->fdes,data,8) != 8 ) break;
n = str2ulong(data+4);
/* The movi list may contain sub-lists, ignore them */
if(strncasecmp(data,"LIST",4)==0)
{
lseek(AVI->fdes,4,SEEK_CUR);
continue;
}
/* Check if we got a tag ##db, ##dc or ##wb */
if( ( (data[2]=='d' || data[2]=='D') &&
(data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') )
|| ( (data[2]=='w' || data[2]=='W') &&
(data[3]=='b' || data[3]=='B') ) )
{
avi_add_index_entry(AVI,data,0,lseek(AVI->fdes,0,SEEK_CUR)-8,n);
}
lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR);
}
idx_type = 1;
}
/* Now generate the video index and audio index arrays */
nvi = 0;
nai = 0;
for(i=0;i<AVI->n_idx;i++)
{
if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) nvi++;
if(strncasecmp(AVI->idx[i],AVI->audio_tag,4) == 0) nai++;
}
AVI->video_frames = nvi;
AVI->audio_chunks = nai;
if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS)
AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry));
if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM)
if(AVI->audio_chunks)
{
AVI->audio_index = (audio_index_entry *) malloc(nai*sizeof(audio_index_entry));
if(AVI->audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM)
}
nvi = 0;
nai = 0;
tot = 0;
ioff = idx_type == 1 ? 8 : AVI->movi_start+4;
for(i=0;i<AVI->n_idx;i++)
{
if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0)
{
AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12);
nvi++;
}
if(strncasecmp(AVI->idx[i],AVI->audio_tag,4) == 0)
{
AVI->audio_index[nai].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
AVI->audio_index[nai].len = str2ulong(AVI->idx[i]+12);
AVI->audio_index[nai].tot = tot;
tot += AVI->audio_index[nai].len;
nai++;
}
}
AVI->audio_bytes = tot;
/* Reposition the file */
lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
AVI->video_pos = 0;
return AVI;
}
long AVI_video_frames(avi_t *AVI)
{
return AVI->video_frames;
}
int AVI_video_width(avi_t *AVI)
{
return AVI->width;
}
int AVI_video_height(avi_t *AVI)
{
return AVI->height;
}
double AVI_video_frame_rate(avi_t *AVI)
{
return AVI->fps;
}
char* AVI_video_compressor(avi_t *AVI)
{
return AVI->compressor;
}
int AVI_audio_channels(avi_t *AVI)
{
return AVI->a_chans;
}
int AVI_audio_bits(avi_t *AVI)
{
return AVI->a_bits;
}
int AVI_audio_format(avi_t *AVI)
{
return AVI->a_fmt;
}
long AVI_audio_rate(avi_t *AVI)
{
return AVI->a_rate;
}
long AVI_audio_bytes(avi_t *AVI)
{
return AVI->audio_bytes;
}
long AVI_frame_size(avi_t *AVI, long frame)
{
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
if(frame < 0 || frame >= AVI->video_frames) return 0;
return(AVI->video_index[frame].len);
}
int AVI_seek_start(avi_t *AVI)
{
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
AVI->video_pos = 0;
AVI->audio_posc = 0;
AVI->audio_posb = 0;
return 0;
}
int AVI_set_video_position(avi_t *AVI, long frame, long *frame_len)
{
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
if (frame < 0 ) frame = 0;
AVI->video_pos = frame;
if (frame_len != NULL)
*frame_len = AVI->video_index[frame].len;
return 0;
}
long AVI_read_frame(avi_t *AVI, char *vidbuf)
{
long n;
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return 0;
n = AVI->video_index[AVI->video_pos].len;
lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET);
if (read(AVI->fdes,vidbuf,n) != n)
{
AVI_errno = AVI_ERR_READ;
return -1;
}
AVI->video_pos++;
return n;
}
int AVI_set_audio_position(avi_t *AVI, long byte)
{
long n0, n1, n;
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(!AVI->audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
if(byte < 0) byte = 0;
/* Binary search in the audio chunks */
n0 = 0;
n1 = AVI->audio_chunks;
while(n0<n1-1)
{
n = (n0+n1)/2;
if(AVI->audio_index[n].tot>byte)
n1 = n;
else
n0 = n;
}
AVI->audio_posc = n0;
AVI->audio_posb = byte - AVI->audio_index[n0].tot;
return 0;
}
int AVI_set_audio_frame (avi_t *AVI, long frame, long *frame_len)
{
if (AVI->audio_posc >= AVI->audio_chunks - 1) { return -1; }
AVI->audio_posc = frame;
AVI->audio_posb = 0;
if (frame_len != NULL)
*frame_len = AVI->audio_index[frame].len;
return 0;
}
long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes)
{
long nr, pos, left, todo;
if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(!AVI->audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
nr = 0; /* total number of bytes read */
while(bytes>0)
{
left = AVI->audio_index[AVI->audio_posc].len - AVI->audio_posb;
if(left==0)
{
if(AVI->audio_posc>=AVI->audio_chunks-1) return nr;
AVI->audio_posc++;
AVI->audio_posb = 0;
continue;
}
if(bytes<left)
todo = bytes;
else
todo = left;
pos = AVI->audio_index[AVI->audio_posc].pos + AVI->audio_posb;
lseek(AVI->fdes, pos, SEEK_SET);
if (read(AVI->fdes,audbuf+nr,todo) != todo)
{
AVI_errno = AVI_ERR_READ;
return -1;
}
bytes -= todo;
nr += todo;
AVI->audio_posb += todo;
}
return nr;
}
/* AVI_read_data: Special routine for reading the next audio or video chunk
without having an index of the file. */
int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf,
char *audbuf, long max_audbuf,
long *len)
{
/*
* Return codes:
*
* 1 = video data read
* 2 = audio data read
* 0 = reached EOF
* -1 = video buffer too small
* -2 = audio buffer too small
*/
int n;
char data[8];
if(AVI->mode==AVI_MODE_WRITE) return 0;
while(1)
{
/* Read tag and length */
if( read(AVI->fdes,data,8) != 8 ) return 0;
/* if we got a list tag, ignore it */
if(strncasecmp(data,"LIST",4) == 0)
{
lseek(AVI->fdes,4,SEEK_CUR);
continue;
}
n = PAD_EVEN(str2ulong(data+4));
if(strncasecmp(data,AVI->video_tag,3) == 0)
{
*len = n;
AVI->video_pos++;
if(n>max_vidbuf)
{
lseek(AVI->fdes,n,SEEK_CUR);
return -1;
}
if(read(AVI->fdes,vidbuf,n) != n ) return 0;
return 1;
}
else if(strncasecmp(data,AVI->audio_tag,4) == 0)
{
*len = n;
if(n>max_audbuf)
{
lseek(AVI->fdes,n,SEEK_CUR);
return -2;
}
if(read(AVI->fdes,audbuf,n) != n ) return 0;
return 2;
break;
}
else
if(lseek(AVI->fdes,n,SEEK_CUR)<0) return 0;
}
}
/* AVI_print_error: Print most recent error (similar to perror) */
char *(avi_errors[]) =
{
/* 0 */ "avilib - No Error",
/* 1 */ "avilib - AVI file size limit reached",
/* 2 */ "avilib - Error opening AVI file",
/* 3 */ "avilib - Error reading from AVI file",
/* 4 */ "avilib - Error writing to AVI file",
/* 5 */ "avilib - Error writing index (file may still be useable)",
/* 6 */ "avilib - Error closing AVI file",
/* 7 */ "avilib - Operation (read/write) not permitted",
/* 8 */ "avilib - Out of memory (malloc failed)",
/* 9 */ "avilib - Not an AVI file",
/* 10 */ "avilib - AVI file has no header list (corrupted?)",
/* 11 */ "avilib - AVI file has no MOVI list (corrupted?)",
/* 12 */ "avilib - AVI file has no video data",
/* 13 */ "avilib - operation needs an index",
/* 14 */ "avilib - Unkown Error"
};
static int num_avi_errors = sizeof(avi_errors)/sizeof(char*);
static char error_string[4096];
void AVI_print_error(char *str)
{
int aerrno;
aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;
fprintf(stderr,"%s: %s\n",str,avi_errors[aerrno]);
/* for the following errors, perror should report a more detailed reason: */
if(AVI_errno == AVI_ERR_OPEN ||
AVI_errno == AVI_ERR_READ ||
AVI_errno == AVI_ERR_WRITE ||
AVI_errno == AVI_ERR_WRITE_INDEX ||
AVI_errno == AVI_ERR_CLOSE )
{
perror("REASON");
}
}
char *AVI_strerror()
{
int aerrno;
aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;
if(AVI_errno == AVI_ERR_OPEN ||
AVI_errno == AVI_ERR_READ ||
AVI_errno == AVI_ERR_WRITE ||
AVI_errno == AVI_ERR_WRITE_INDEX ||
AVI_errno == AVI_ERR_CLOSE )
{
sprintf(error_string,"%s - %s",avi_errors[aerrno],
#ifndef _WINDOWS
strerror(errno)
#else
_strerror(NULL)
#endif
);
return error_string;
}
else
{
return avi_errors[aerrno];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -