📄 avilib.c
字号:
+ 4+4+2+1+1+4+4+8+4; } } towrite += len + (len&1) + 8; //GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML: towrite = 0x%llX = %lld\n", towrite, towrite)); if (AVI->video_superindex && (s64)(AVI->pos+towrite) > (s64)((s64)NEW_RIFF_THRES*AVI->video_superindex->nEntriesInUse)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] Adding a new RIFF chunk: %d\n", AVI->video_superindex->nEntriesInUse)); // rotate ALL indices AVI->video_superindex->nEntriesInUse++; cur_std_idx = AVI->video_superindex->nEntriesInUse-1; if (AVI->video_superindex->nEntriesInUse > NR_IXNN_CHUNKS) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[avilib] Internal error in avilib - redefine NR_IXNN_CHUNKS\n")); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] cur_std_idx=%d NR_IXNN_CHUNKS=%d" "POS=%lld towrite=%lld\n", cur_std_idx,NR_IXNN_CHUNKS, AVI->pos, towrite)); return -1; } if (avi_add_std_index (AVI, (unsigned char *)"ix00", (unsigned char *)"00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) return -1; for (audtr = 0; audtr < AVI->anum; audtr++) { char aud[5]; if (!AVI->track[audtr].audio_superindex) { // not initialized -> no index continue; } AVI->track[audtr].audio_superindex->nEntriesInUse++; sprintf(fcc, "ix%02d", audtr+1); sprintf(aud, "0%01dwb", audtr+1); if (avi_add_std_index (AVI, (unsigned char *)fcc, (unsigned char *)aud, AVI->track[audtr].audio_superindex->stdindex[ AVI->track[audtr].audio_superindex->nEntriesInUse - 1 ]) < 0 ) return -1; } // write the new riff; if (cur_std_idx > 0) { // dump the _previous_ == already finished index avi_ixnn_entry (AVI, AVI->video_superindex->stdindex[cur_std_idx - 1], &AVI->video_superindex->aIndex[cur_std_idx - 1]); AVI->video_superindex->aIndex[cur_std_idx - 1].dwDuration = AVI->video_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; for (audtr = 0; audtr < AVI->anum; audtr++) { if (!AVI->track[audtr].audio_superindex) { // not initialized -> no index continue; } avi_ixnn_entry (AVI, AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1], &AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1]); AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration = AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; if (AVI->track[audtr].a_fmt == 0x1) { AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration *= AVI->track[audtr].a_bits*AVI->track[audtr].a_rate*AVI->track[audtr].a_chans/800; } } // XXX: dump idx1 structure if (cur_std_idx == 1) { avi_add_chunk(AVI, (unsigned char *)"idx1", (unsigned char *)AVI->idx, AVI->n_idx*16); // qwBaseOffset will contain the start of the second riff chunk } // Fix the Offsets later at closing time avi_add_chunk(AVI, (unsigned char *)"RIFF", (unsigned char *)"AVIXLIST\0\0\0\0movi", 16); AVI->video_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = AVI->pos -16 -8;#ifdef DEBUG_ODML GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] ODML: RIFF No.%02d at Offset 0x%llX\n", cur_std_idx, AVI->pos -16 -8));#endif for (audtr = 0; audtr < AVI->anum; audtr++) { if (AVI->track[audtr].audio_superindex) AVI->track[audtr].audio_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = AVI->pos -16 -8; } // now we can be sure AVI->is_opendml++; } } if (video) { avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, AVI->video_superindex->stdindex[ AVI->video_superindex->nEntriesInUse-1 ]); AVI->total_frames++; } // video if (audio) { avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, AVI->track[AVI->aptr].audio_superindex->stdindex[ AVI->track[AVI->aptr].audio_superindex->nEntriesInUse-1 ]); } return 0;}// #undef NR_IXNN_CHUNKSstatic int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, u64 pos, u64 len){ void *ptr; if(AVI->n_idx>=AVI->max_idx) { ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16); if(ptr == 0) { AVI_errno = AVI_ERR_NO_MEM; return -1; } AVI->max_idx += 4096; AVI->idx = (unsigned char((*)[16]) ) ptr; } /* Add index entry */ // GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] INDEX %s %ld %lu %lu\n", tag, flags, pos, len)); memcpy(AVI->idx[AVI->n_idx],tag,4); long2str(AVI->idx[AVI->n_idx]+ 4,flags); long2str(AVI->idx[AVI->n_idx]+ 8, (s32) pos); long2str(AVI->idx[AVI->n_idx]+12, (s32) len); /* Update counter */ AVI->n_idx++; if(len>AVI->max_len) AVI->max_len=(u32) len; return 0;}/* Returns 1 if more audio is in that video junk */int AVI_can_read_audio(avi_t *AVI){ if(AVI->mode==AVI_MODE_WRITE) { return -1; } if(!AVI->video_index) { return -1; } if(!AVI->track[AVI->aptr].audio_index) { return -1; } // is it -1? the last ones got left out --tibit //if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) { if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks) { return 0; } if (AVI->video_pos >= AVI->video_frames) return 1; if (AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos < AVI->video_index[AVI->video_pos].pos) return 1; else return 0;}/* AVI_open_output_file: Open an AVI File and write a bunch of zero bytes as space for the header. returns a pointer to avi_t on success, a zero pointer on error*/GF_EXPORTavi_t* AVI_open_output_file(char * filename){ avi_t *AVI; int i; unsigned char AVI_header[HEADERBYTES]; /* Allocate the avi_t struct and zero it */ AVI = (avi_t *) malloc(sizeof(avi_t)); if(AVI==0) { AVI_errno = AVI_ERR_NO_MEM; return 0; } memset((void *)AVI,0,sizeof(avi_t)); AVI->fdes = gf_f64_open(filename, "w+b"); if (!AVI->fdes ) { AVI_errno = AVI_ERR_OPEN; free(AVI); return 0; } /* Write out HEADERBYTES bytes, the header will go here when we are finished with writing */ for (i=0;i<HEADERBYTES;i++) AVI_header[i] = 0; i = avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES); if (i != HEADERBYTES) { fclose(AVI->fdes); AVI_errno = AVI_ERR_WRITE; free(AVI); return 0; } AVI->pos = HEADERBYTES; AVI->mode = AVI_MODE_WRITE; /* open for writing */ //init AVI->anum = 0; AVI->aptr = 0; return AVI;}GF_EXPORTvoid AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor){ /* may only be called if file is open for writing */ if(AVI->mode==AVI_MODE_READ) return; AVI->width = width; AVI->height = height; AVI->fps = fps; if(strncmp(compressor, "RGB", 3)==0) { memset(AVI->compressor, 0, 4); } else { memcpy(AVI->compressor,compressor,4); } AVI->compressor[4] = 0; avi_update_header(AVI);}void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate){ /* may only be called if file is open for writing */ if(AVI->mode==AVI_MODE_READ) return; //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)); exit(1); } AVI->track[AVI->aptr].a_chans = channels; AVI->track[AVI->aptr].a_rate = rate; AVI->track[AVI->aptr].a_bits = bits; AVI->track[AVI->aptr].a_fmt = format; AVI->track[AVI->aptr].mp3rate = mp3rate; avi_update_header(AVI);}#define OUT4CC(s) \ if(nhb<=HEADERBYTES-4) memcpy(AVI_header+nhb,s,4); nhb += 4#define OUTLONG(n) \ if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb, (s32)(n)); nhb += 4#define OUTSHRT(n) \ if(nhb<=HEADERBYTES-2) { \ AVI_header[nhb ] = (u8) ((n )&0xff); \ AVI_header[nhb+1] = (u8) ((n>>8)&0xff); \ } \ nhb += 2#define OUTCHR(n) \ if(nhb<=HEADERBYTES-1) { \ AVI_header[nhb ] = (n )&0xff; \ } \ nhb += 1#define OUTMEM(d, s) \ { \ u32 s_ = (u32) (s); \ if(nhb + s_ <= HEADERBYTES) \ memcpy(AVI_header+nhb, (d), s_); \ nhb += s_; \ }//ThOe write preliminary AVI file header: 0 frames, max vid/aud sizeint avi_update_header(avi_t *AVI){ int njunk, sampsize, hasIndex, ms_per_frame, frate, flag; int movi_len, hdrl_start, strl_start; u32 j; unsigned char AVI_header[HEADERBYTES]; u32 nhb; unsigned long xd_size, xd_size_align2; //assume max size movi_len = AVI_MAX_LEN - HEADERBYTES + 4; //assume index will be written hasIndex=1; if(AVI->fps < 0.001) { frate=0; ms_per_frame=0; } else { frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); ms_per_frame=(int) (1000000/AVI->fps + 0.5); } /* Prepare the file header */ nhb = 0; /* The RIFF header */ OUT4CC ("RIFF"); OUTLONG(movi_len); // assume max size OUT4CC ("AVI "); /* Start the header list */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ hdrl_start = nhb; /* Store start position */ OUT4CC ("hdrl"); /* The main AVI header */ /* The Flags in AVI File header */#define AVIF_HASINDEX 0x00000010 /* Index at end of file */#define AVIF_MUSTUSEINDEX 0x00000020#define AVIF_ISINTERLEAVED 0x00000100#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */#define AVIF_WASCAPTUREFILE 0x00010000#define AVIF_COPYRIGHTED 0x00020000 OUT4CC ("avih"); OUTLONG(56); /* # of bytes to follow */ OUTLONG(ms_per_frame); /* Microseconds per frame */ //ThOe ->0 // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ OUTLONG(0); OUTLONG(0); /* PaddingGranularity (whatever that might be) */ /* Other sources call it 'reserved' */ flag = AVIF_ISINTERLEAVED; if(hasIndex) flag |= AVIF_HASINDEX; if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; OUTLONG(flag); /* Flags */ OUTLONG(0); // no frames yet OUTLONG(0); /* InitialFrames */ OUTLONG(AVI->anum+1); OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ /* MS calls the following 'reserved': */ OUTLONG(0); /* TimeScale: Unit used to measure time */ OUTLONG(0); /* DataRate: Data rate of playback */ OUTLONG(0); /* StartTime: Starting time of AVI data */ OUTLONG(0); /* DataLength: Size of AVI data chunk */ /* Start the video stream list ---------------------------------- */ OUT4CC ("LIST"); OUTLONG(0); /* Length of list in bytes, don't know yet */ strl_start = nhb; /* Store start position */ OUT4CC ("strl"); /* The video stream header */ OUT4CC ("strh"); OUTLONG(56); /* # of bytes to follow */ OUT4CC ("vids"); /* Type */ OUT4CC (AVI->compressor); /* Handler */ OUTLONG(0); /* Flags */ OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ OUTLONG(0); /* InitialFrames */ OUTLONG(FRAME_RATE_SCALE); /* Scale */ OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ OUTLONG(0); /* Start */ OUTLONG(0); // no frames yet OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(-1); /* Quality */ OUTLONG(0); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ // OUTLONG(0); /* Frame */ //OUTLONG(0); /* Frame */ /* The video stream format */ xd_size = AVI->extradata_size; xd_size_align2 = (AVI->extradata_size+1) & ~1; OUT4CC ("strf"); OUTLONG(40 + xd_size_align2);/* # of bytes to follow */ OUTLONG(40 + xd_size); /* Size */ OUTLONG(AVI->width); /* Width */ OUTLONG(AVI->height); /* Height */ OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ OUT4CC (AVI->compressor); /* Compression */ // ThOe (*3) OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ OUTLONG(0); /* XPelsPerMeter */ OUTLONG(0); /* YPelsPerMeter */ OUTLONG(0); /* ClrUsed: Number of colors used */ OUTLONG(0); /* ClrImportant: Number of colors important */ // write extradata if (xd_size > 0 && AVI->extradata) { OUTMEM(AVI->extradata, xd_size); if (xd_size != xd_size_align2) { OUTCHR(0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -