📄 avilib.c
字号:
{ 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,(unsigned char *) 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; for(j=0; j<AVI->anum; ++j) nai[j] = 0; for(i=0;i<AVI->n_idx;i++) { if(strncasecmp((char *)AVI->idx[i],(char *) AVI->video_tag,3) == 0) nvi++; for(j=0; j<AVI->anum; ++j) if(strncasecmp((char *)AVI->idx[i], AVI->track[j].audio_tag,4) == 0) nai[j]++; } AVI->video_frames = nvi; for(j=0; j<AVI->anum; ++j) AVI->track[j].audio_chunks = nai[j];// fprintf(stderr, "chunks = %ld %d %s\n", AVI->track[0].audio_chunks, AVI->anum, AVI->track[0].audio_tag); 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); for(j=0; j<AVI->anum; ++j) { if(AVI->track[j].audio_chunks) { AVI->track[j].audio_index = (audio_index_entry *) malloc(nai[j]*sizeof(audio_index_entry)); if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); } } nvi = 0; for(j=0; j<AVI->anum; ++j) nai[j] = tot[j] = 0; ioff = idx_type == 1 ? 8 : AVI->movi_start+4; for(i=0;i<AVI->n_idx;i++) { //video if(strncasecmp((char *)AVI->idx[i],(char *)AVI->video_tag,3) == 0) { AVI->video_index[nvi].key = str2ulong(AVI->idx[i]+ 4); AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff; AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12); nvi++; } //audio for(j=0; j<AVI->anum; ++j) { if(strncasecmp((char *)AVI->idx[i],AVI->track[j].audio_tag,4) == 0) { AVI->track[j].audio_index[nai[j]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; AVI->track[j].audio_index[nai[j]].len = str2ulong(AVI->idx[i]+12); AVI->track[j].audio_index[nai[j]].tot = tot[j]; tot[j] += AVI->track[j].audio_index[nai[j]].len; nai[j]++; } } } for(j=0; j<AVI->anum; ++j) AVI->track[j].audio_bytes = tot[j]; /* Reposition the file */ lseek(AVI->fdes,AVI->movi_start,SEEK_SET); AVI->video_pos = 0; return(0);}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_frame_rate(avi_t *AVI){ return AVI->fps;}char* AVI_video_compressor(avi_t *AVI){ return AVI->compressor2;}long AVI_max_video_chunk(avi_t *AVI){ return AVI->max_len; }int AVI_audio_tracks(avi_t *AVI){ return(AVI->anum);}int AVI_audio_channels(avi_t *AVI){ return AVI->track[AVI->aptr].a_chans;}long AVI_audio_mp3rate(avi_t *AVI){ return AVI->track[AVI->aptr].mp3rate;}int AVI_audio_bits(avi_t *AVI){ return AVI->track[AVI->aptr].a_bits;}int AVI_audio_format(avi_t *AVI){ return AVI->track[AVI->aptr].a_fmt;}long AVI_audio_rate(avi_t *AVI){ return AVI->track[AVI->aptr].a_rate;}long AVI_audio_bytes(avi_t *AVI){ return AVI->track[AVI->aptr].audio_bytes;}long AVI_audio_chunks(avi_t *AVI){ return AVI->track[AVI->aptr].audio_chunks;}long AVI_audio_codech_offset(avi_t *AVI){ return AVI->track[AVI->aptr].a_codech_off;}long AVI_audio_codecf_offset(avi_t *AVI){ return AVI->track[AVI->aptr].a_codecf_off;}long AVI_video_codech_offset(avi_t *AVI){ return AVI->v_codech_off;}long AVI_video_codecf_offset(avi_t *AVI){ return AVI->v_codecf_off;}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);}long AVI_audio_size(avi_t *AVI, long frame){ if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } if(frame < 0 || frame >= AVI->track[AVI->aptr].audio_chunks) return 0; return(AVI->track[AVI->aptr].audio_index[frame].len);}long AVI_get_video_position(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].pos);}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; return 0;}int AVI_set_video_position(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 = 0; AVI->video_pos = frame; return 0;}int AVI_set_audio_bitrate(avi_t *AVI, long bitrate){ if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } AVI->track[AVI->aptr].mp3rate = bitrate; return 0;} long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe){ 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 -1; n = AVI->video_index[AVI->video_pos].len; *keyframe = (AVI->video_index[AVI->video_pos].key==0x10) ? 1:0; lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET); if (avi_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->track[AVI->aptr].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->track[AVI->aptr].audio_chunks; while(n0<n1-1) { n = (n0+n1)/2; if(AVI->track[AVI->aptr].audio_index[n].tot>byte) n1 = n; else n0 = n; } AVI->track[AVI->aptr].audio_posc = n0; AVI->track[AVI->aptr].audio_posb = byte - AVI->track[AVI->aptr].audio_index[n0].tot; 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->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } nr = 0; /* total number of bytes read */ while(bytes>0) { left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; if(left==0) { if(AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) return nr; AVI->track[AVI->aptr].audio_posc++; AVI->track[AVI->aptr].audio_posb = 0; continue; } if(bytes<left) todo = bytes; else todo = left; pos = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; lseek(AVI->fdes, pos, SEEK_SET); if (avi_read(AVI->fdes,audbuf+nr,todo) != todo) { AVI_errno = AVI_ERR_READ; return -1; } bytes -= todo; nr += todo; AVI->track[AVI->aptr].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( avi_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((unsigned char *)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(avi_read(AVI->fdes,vidbuf,n) != n ) return 0; return 1; } else if(strncasecmp(data,AVI->track[AVI->aptr].audio_tag,4) == 0) { *len = n; if(n>max_audbuf) { lseek(AVI->fdes,n,SEEK_CUR); return -2; } if(avi_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],strerror(errno)); return error_string; } else { return avi_errors[aerrno]; }}uint64_t AVI_max_size(){ return((uint64_t) AVI_MAX_LEN);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -