📄 avilib.c
字号:
/* If the file was open for writing, the header and index still have to be written */ if(AVI->mode == AVI_MODE_WRITE) ret = avi_close_output_file(AVI); else ret = 0; /* Even if there happened an error, we first clean up */ fclose(AVI->fdes); if(AVI->idx) free(AVI->idx); if(AVI->video_index) free(AVI->video_index); if(AVI->video_superindex) { if(AVI->video_superindex->aIndex) free(AVI->video_superindex->aIndex); if (AVI->video_superindex->stdindex) { for (j=0; j < NR_IXNN_CHUNKS; j++) { if (AVI->video_superindex->stdindex[j]->aIndex) free(AVI->video_superindex->stdindex[j]->aIndex); free(AVI->video_superindex->stdindex[j]); } free(AVI->video_superindex->stdindex); } free(AVI->video_superindex); } for (j=0; j<AVI->anum; j++) { if(AVI->track[j].audio_index) free(AVI->track[j].audio_index); if(AVI->track[j].audio_superindex) { if(AVI->track[j].audio_superindex->aIndex) free(AVI->track[j].audio_superindex->aIndex); free(AVI->track[j].audio_superindex); } } if (AVI->bitmap_info_header) free(AVI->bitmap_info_header); for (j = 0; j < AVI->anum; j++) if (AVI->wave_format_ex[j]) free(AVI->wave_format_ex[j]); free(AVI); AVI=NULL; return ret;}#define ERR_EXIT(x) \{ \ AVI_close(AVI); \ AVI_errno = x; \ return 0; \}avi_t *AVI_open_input_file(char *filename, int getIndex){ avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ /* Open the file */ AVI->fdes = gf_f64_open(filename,"rb"); if(!AVI->fdes ) { AVI_errno = AVI_ERR_OPEN; free(AVI); return 0; } AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) { free(AVI); return NULL; } return AVI;}avi_t *AVI_open_fd(FILE *fd, int getIndex){ avi_t *AVI=NULL; /* Create avi_t structure */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==NULL) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->mode = AVI_MODE_READ; /* open for reading */ // file alread open AVI->fdes = fd; AVI_errno = 0; avi_parse_input_file(AVI, getIndex); if (AVI != NULL && !AVI_errno) { AVI->aptr=0; //reset } if (AVI_errno) return AVI=NULL; else return AVI;}int avi_parse_input_file(avi_t *AVI, int getIndex){ long i, rate, scale, idx_type; s64 n; unsigned char *hdrl_data; long header_offset=0, hdrl_len=0; long nvi, nai[AVI_MAX_TRACKS], ioff; u64 tot[AVI_MAX_TRACKS]; u32 j; int lasttag = 0; int vids_strh_seen = 0; int vids_strf_seen = 0; int auds_strh_seen = 0; // int auds_strf_seen = 0; int num_stream = 0; char data[256]; s64 oldpos=-1, newpos=-1; long aud_chunks = 0; /* Read first 12 bytes and check that this is an AVI file */ if( avi_read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ) if( strnicmp(data ,"RIFF",4) !=0 || strnicmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI) /* Go through the AVI file and extract the header list, the start position of the 'movi' list and an optionally present idx1 tag */ hdrl_data = 0; while(1) { if( avi_read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */ newpos = gf_f64_tell(AVI->fdes); if(oldpos==newpos) { /* This is a broken AVI stream... */ return -1; } oldpos=newpos; n = str2ulong((unsigned char *)data+4); n = PAD_EVEN(n); if(strnicmp(data,"LIST",4) == 0) { if( avi_read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ) n -= 4; if(strnicmp(data,"hdrl",4) == 0) { hdrl_len = (u32) n; hdrl_data = (unsigned char *) malloc((u32)n); if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM); // offset of header header_offset = (u32) gf_f64_tell(AVI->fdes); if( avi_read(AVI->fdes,(char *)hdrl_data, (u32) n) != n ) ERR_EXIT(AVI_ERR_READ) } else if(strnicmp(data,"movi",4) == 0) { AVI->movi_start = gf_f64_tell(AVI->fdes); if (gf_f64_seek(AVI->fdes,n,SEEK_CUR)==(u64)-1) break; } else if (gf_f64_seek(AVI->fdes,n,SEEK_CUR)==(u64)-1) break; } else if(strnicmp(data,"idx1",4) == 0) { /* n must be a multiple of 16, but the reading does not break if this is not the case */ AVI->n_idx = AVI->max_idx = (u32) (n/16); AVI->idx = (unsigned char((*)[16]) ) malloc((u32)n); if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM) if(avi_read(AVI->fdes, (char *) AVI->idx, (u32) n) != n ) { free ( AVI->idx); AVI->idx=NULL; AVI->n_idx = 0; } } else gf_f64_seek(AVI->fdes,n,SEEK_CUR); } if(!hdrl_data ) ERR_EXIT(AVI_ERR_NO_HDRL) if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI) /* Interpret the header list */ for(i=0;i<hdrl_len;) { /* List tags are completly ignored */#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] TAG %c%c%c%c\n", (hdrl_data+i)[0], (hdrl_data+i)[1], (hdrl_data+i)[2], (hdrl_data+i)[3]));#endif if(strnicmp((char *)hdrl_data+i,"LIST",4)==0) { i+= 12; continue; } n = str2ulong(hdrl_data+i+4); n = PAD_EVEN(n); /* Interpret the tag and its args */ if(strnicmp((char *)hdrl_data+i,"strh",4)==0) { i += 8;#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] TAG %c%c%c%c\n", (hdrl_data+i)[0], (hdrl_data+i)[1], (hdrl_data+i)[2], (hdrl_data+i)[3]));#endif if(strnicmp((char *)hdrl_data+i,"vids",4) == 0 && !vids_strh_seen) { memcpy(AVI->compressor,hdrl_data+i+4,4); AVI->compressor[4] = 0; // ThOe AVI->v_codech_off = header_offset + i+4; scale = str2ulong(hdrl_data+i+20); rate = str2ulong(hdrl_data+i+24); if(scale!=0) AVI->fps = (double)rate/(double)scale; AVI->video_frames = str2ulong(hdrl_data+i+32); AVI->video_strn = num_stream; AVI->max_len = 0; vids_strh_seen = 1; lasttag = 1; /* vids */ memcpy(&AVI->video_stream_header, hdrl_data + i, sizeof(alAVISTREAMHEADER)); } else if (strnicmp ((char *)hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen) { //inc audio tracks AVI->aptr=AVI->anum; ++AVI->anum; if(AVI->anum > AVI_MAX_TRACKS) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[avilib] error - only %d audio tracks supported\n", AVI_MAX_TRACKS)); return(-1); } AVI->track[AVI->aptr].audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, 0); AVI->track[AVI->aptr].audio_strn = num_stream; // if samplesize==0 -> vbr AVI->track[AVI->aptr].a_vbr = !str2ulong(hdrl_data+i+44); AVI->track[AVI->aptr].padrate = str2ulong(hdrl_data+i+24); memcpy(&AVI->stream_headers[AVI->aptr], hdrl_data + i, sizeof(alAVISTREAMHEADER)); // auds_strh_seen = 1; lasttag = 2; /* auds */ // ThOe AVI->track[AVI->aptr].a_codech_off = header_offset + i; } else if (strnicmp ((char*)hdrl_data+i,"iavs",4) ==0 && ! auds_strh_seen) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[avilib] AVILIB: error - DV AVI Type 1 no supported\n")); return (-1); } else lasttag = 0; num_stream++; } else if(strnicmp((char*)hdrl_data+i,"dmlh",4) == 0) { AVI->total_frames = str2ulong(hdrl_data+i+8);#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] real number of frames %d\n", AVI->total_frames));#endif i += 8; } else if(strnicmp((char *)hdrl_data+i,"strf",4)==0) { i += 8; if(lasttag == 1) { alBITMAPINFOHEADER bih; memcpy(&bih, hdrl_data + i, sizeof(alBITMAPINFOHEADER)); AVI->bitmap_info_header = (alBITMAPINFOHEADER *) malloc(str2ulong((unsigned char *)&bih.bi_size)); if (AVI->bitmap_info_header != NULL) memcpy(AVI->bitmap_info_header, hdrl_data + i, str2ulong((unsigned char *)&bih.bi_size)); AVI->width = str2ulong(hdrl_data+i+4); AVI->height = str2ulong(hdrl_data+i+8); vids_strf_seen = 1; //ThOe AVI->v_codecf_off = header_offset + i+16; memcpy(AVI->compressor2, hdrl_data+i+16, 4); AVI->compressor2[4] = 0; } else if(lasttag == 2) { alWAVEFORMATEX *wfe; char *nwfe; int wfes; if ((u32) (hdrl_len - i) < sizeof(alWAVEFORMATEX)) wfes = hdrl_len - i; else wfes = sizeof(alWAVEFORMATEX); wfe = (alWAVEFORMATEX *)malloc(sizeof(alWAVEFORMATEX)); if (wfe != NULL) { memset(wfe, 0, sizeof(alWAVEFORMATEX)); memcpy(wfe, hdrl_data + i, wfes); if (str2ushort((unsigned char *)&wfe->cb_size) != 0) { nwfe = (char *) realloc(wfe, sizeof(alWAVEFORMATEX) + str2ushort((unsigned char *)&wfe->cb_size)); if (nwfe != 0) { s64 lpos = gf_f64_tell(AVI->fdes); gf_f64_seek(AVI->fdes, header_offset + i + sizeof(alWAVEFORMATEX), SEEK_SET); wfe = (alWAVEFORMATEX *)nwfe; nwfe = &nwfe[sizeof(alWAVEFORMATEX)]; avi_read(AVI->fdes, nwfe, str2ushort((unsigned char *)&wfe->cb_size)); gf_f64_seek(AVI->fdes, lpos, SEEK_SET); } } AVI->wave_format_ex[AVI->aptr] = wfe; } AVI->track[AVI->aptr].a_fmt = str2ushort(hdrl_data+i ); //ThOe AVI->track[AVI->aptr].a_codecf_off = header_offset + i; AVI->track[AVI->aptr].a_chans = str2ushort(hdrl_data+i+2); AVI->track[AVI->aptr].a_rate = str2ulong (hdrl_data+i+4); //ThOe: read mp3bitrate AVI->track[AVI->aptr].mp3rate = 8*str2ulong(hdrl_data+i+8)/1000; //:ThOe AVI->track[AVI->aptr].a_bits = str2ushort(hdrl_data+i+14); // auds_strf_seen = 1; } } else if(strnicmp((char*)hdrl_data+i,"indx",4) == 0) { char *a; if(lasttag == 1) // V I D E O { a = (char*)hdrl_data+i; AVI->video_superindex = (avisuperindex_chunk *) malloc (sizeof (avisuperindex_chunk)); memcpy (AVI->video_superindex->fcc, a, 4); a += 4; AVI->video_superindex->dwSize = str2ulong((unsigned char *)a); a += 4; AVI->video_superindex->wLongsPerEntry = str2ushort((unsigned char *)a); a += 2; AVI->video_superindex->bIndexSubType = *a; a += 1; AVI->video_superindex->bIndexType = *a; a += 1; AVI->video_superindex->nEntriesInUse = str2ulong((unsigned char *)a); a += 4; memcpy (AVI->video_superindex->dwChunkId, a, 4); a += 4; // 3 * reserved a += 4; a += 4; a += 4; if (AVI->video_superindex->bIndexSubType != 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[avilib] Invalid Header, bIndexSubType != 0\n")); } AVI->video_superindex->aIndex = (avisuperindex_entry*) malloc (AVI->video_superindex->wLongsPerEntry * AVI->video_superindex->nEntriesInUse * sizeof (u32)); // position of ix## chunks for (j=0; j<AVI->video_superindex->nEntriesInUse; ++j) { AVI->video_superindex->aIndex[j].qwOffset = str2ullong ((unsigned char*)a); a += 8; AVI->video_superindex->aIndex[j].dwSize = str2ulong ((unsigned char*)a); a += 4; AVI->video_superindex->aIndex[j].dwDuration = str2ulong ((unsigned char*)a); a += 4;#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] [%d] 0x%llx 0x%lx %lu\n", j, (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset, (unsigned long)AVI->video_superindex->aIndex[j].dwSize, (unsigned long)AVI->video_superindex->aIndex[j].dwDuration));#endif }#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] FOURCC \"%c%c%c%c\"\n", AVI->video_superindex->fcc[0], AVI->video_superindex->fcc[1], AVI->video_superindex->fcc[2], AVI->video_superindex->fcc[3])); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] LEN \"%ld\"\n", (long)AVI->video_superindex->dwSize)); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] wLongsPerEntry \"%d\"\n", AVI->video_superindex->wLongsPerEntry)); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] bIndexSubType \"%d\"\n", AVI->video_superindex->bIndexSubType)); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] bIndexType \"%d\"\n", AVI->video_superind
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -