📄 avilib.c
字号:
if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { OUTLONG(nBlockAlign); /* Scale */ OUTLONG(AVI->track[j].a_rate); /* Rate */ OUTLONG(0); /* Start */ OUTLONG(AVI->track[j].audio_chunks); /* Length */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(0); /* Quality */ OUTLONG(0); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ } else { OUTLONG(sampsize/4); /* Scale */ OUTLONG(scalerate); /* Rate */ OUTLONG(0); /* Start */ OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ OUTLONG(0); /* SuggestedBufferSize */ OUTLONG(0xffffffff); /* Quality */ OUTLONG(sampsize/4); /* SampleSize */ OUTLONG(0); /* Frame */ OUTLONG(0); /* Frame */ } /* The audio stream format */ OUT4CC ("strf"); if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { OUTLONG(30); /* # of bytes to follow */ // mplayer writes 28 OUTSHRT(AVI->track[j].a_fmt); /* Format */ // 2 OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ // 2 OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ // 4 //ThOe/tibit OUTLONG(1000*AVI->track[j].mp3rate/8); /* maybe we should write an avg. */ // 4 OUTSHRT(nBlockAlign); /* BlockAlign */ // 2 OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ // 2 OUTSHRT(12); /* cbSize */ // 2 OUTSHRT(1); /* wID */ // 2 OUTLONG(2); /* fdwFlags */ // 4 OUTSHRT(nBlockAlign); /* nBlockSize */ // 2 OUTSHRT(1); /* nFramesPerBlock */ // 2 OUTSHRT(0); /* nCodecDelay */ // 2 } else if (AVI->track[j].a_fmt == 0x55 && !AVI->track[j].a_vbr) { OUTLONG(30); /* # of bytes to follow */ OUTSHRT(AVI->track[j].a_fmt); /* Format */ OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ //ThOe/tibit OUTLONG(1000*AVI->track[j].mp3rate/8); OUTSHRT(sampsize/4); /* BlockAlign */ OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ OUTSHRT(12); /* cbSize */ OUTSHRT(1); /* wID */ OUTLONG(2); /* fdwFlags */ OUTSHRT(nBlockAlign); /* nBlockSize */ OUTSHRT(1); /* nFramesPerBlock */ OUTSHRT(0); /* nCodecDelay */ } else { OUTLONG(18); /* # of bytes to follow */ OUTSHRT(AVI->track[j].a_fmt); /* Format */ OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ //ThOe/tibit OUTLONG(avgbsec); /* Avg bytes/sec */ OUTSHRT(sampsize/4); /* BlockAlign */ OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ OUTSHRT(0); /* cbSize */ } } if (AVI->is_opendml) { u32 k; if (!AVI->track[j].audio_superindex) { // not initialized -> no index continue; } OUT4CC(AVI->track[j].audio_superindex->fcc); /* "indx" */ OUTLONG(2+1+1+4+4+3*4 + AVI->track[j].audio_superindex->nEntriesInUse * (8+4+4)); OUTSHRT(AVI->track[j].audio_superindex->wLongsPerEntry); OUTCHR(AVI->track[j].audio_superindex->bIndexSubType); OUTCHR(AVI->track[j].audio_superindex->bIndexType); OUTLONG(AVI->track[j].audio_superindex->nEntriesInUse); OUT4CC(AVI->track[j].audio_superindex->dwChunkId); OUTLONG(0); OUTLONG(0); OUTLONG(0); for (k = 0; k < AVI->track[j].audio_superindex->nEntriesInUse; k++) { u32 r = (u32) ((AVI->track[j].audio_superindex->aIndex[k].qwOffset >> 32) & 0xffffffff); u32 s = (u32) ((AVI->track[j].audio_superindex->aIndex[k].qwOffset) & 0xffffffff); /* GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[avilib] AUD[%d] NrEntries %d/%ld (%c%c%c%c) |0x%llX|%ld|%ld| \n", j, k, AVI->track[j].audio_superindex->nEntriesInUse, AVI->track[j].audio_superindex->dwChunkId[0], AVI->track[j].audio_superindex->dwChunkId[1], AVI->track[j].audio_superindex->dwChunkId[2], AVI->track[j].audio_superindex->dwChunkId[3], AVI->track[j].audio_superindex->aIndex[k].qwOffset, AVI->track[j].audio_superindex->aIndex[k].dwSize, AVI->track[j].audio_superindex->aIndex[k].dwDuration )); */ OUTLONG(s); OUTLONG(r); OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwSize); OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwDuration); } } /* Finish stream list, i.e. put number of bytes in the list to proper pos */ long2str(AVI_header+strl_start-4,nhb-strl_start); } if (AVI->is_opendml) { OUT4CC("LIST"); OUTLONG(16); OUT4CC("odml"); OUT4CC("dmlh"); OUTLONG(4); OUTLONG(AVI->total_frames); } /* Finish header list */ long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); // add INFO list --- (0.6.0pre4)#ifdef INFO_LIST OUT4CC ("LIST"); info_start_pos = nhb; info_len = MAX_INFO_STRLEN + 12; OUTLONG(info_len); // rewritten later OUT4CC ("INFO"); OUT4CC ("ISFT"); //OUTLONG(MAX_INFO_STRLEN); memset(id_str, 0, MAX_INFO_STRLEN); sprintf(id_str, "%s-%s", PACKAGE, VERSION); real_id_len = id_len = strlen(id_str)+1; if (id_len&1) id_len++; OUTLONG(real_id_len); memset(AVI_header+nhb, 0, id_len); memcpy(AVI_header+nhb, id_str, id_len); nhb += id_len; info_len = 0; // write correct len long2str(AVI_header+info_start_pos, info_len + id_len + 4+4+4); nhb += info_len;// OUT4CC ("ICMT");// OUTLONG(MAX_INFO_STRLEN);// calptr=time(NULL); // sprintf(id_str, "\t%s %s", ctime(&calptr), "");// memset(AVI_header+nhb, 0, MAX_INFO_STRLEN);// memcpy(AVI_header+nhb, id_str, 25);// nhb += MAX_INFO_STRLEN;#endif // ---------------------------- /* Calculate the needed amount of junk bytes, output junk */ njunk = HEADERBYTES - nhb - 8 - 12; /* Safety first: if njunk <= 0, somebody has played with HEADERBYTES without knowing what (s)he did. This is a fatal error */ if(njunk<=0) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[avilib] AVI_close_output_file: # of header bytes too small\n")); exit(1); } OUT4CC ("JUNK"); OUTLONG(njunk); memset(AVI_header+nhb,0,njunk); nhb += njunk; /* Start the movi list */ OUT4CC ("LIST"); OUTLONG(movi_len); /* Length of list in bytes */ OUT4CC ("movi"); /* Output the header, truncate the file to the number of bytes actually written, report an error if someting goes wrong */ if ( gf_f64_seek(AVI->fdes,0,SEEK_SET)<0 || avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES // || ftruncate(AVI->fdes,AVI->pos)<0 ) { AVI_errno = AVI_ERR_CLOSE; return -1; } // Fix up the empty additional RIFF and LIST chunks if (AVI->is_opendml) { u32 k; char f[4]; u32 len; for (k=1; k<AVI->video_superindex->nEntriesInUse; k++) { // the len of the RIFF Chunk gf_f64_seek(AVI->fdes, AVI->video_superindex->stdindex[k]->qwBaseOffset+4, SEEK_SET); len = (u32) (AVI->video_superindex->stdindex[k+1]->qwBaseOffset - AVI->video_superindex->stdindex[k]->qwBaseOffset - 8); long2str((unsigned char *)f, len); avi_write(AVI->fdes, f, 4); // len of the LIST/movi chunk gf_f64_seek(AVI->fdes, 8, SEEK_CUR); len -= 12; long2str((unsigned char *)f, len); avi_write(AVI->fdes, f, 4); } } if(idxerror) return -1; return 0;}/* AVI_write_data: Add video or audio data to the file; Return values: 0 No error; -1 Error, AVI_errno is set appropriatly;*/static int avi_write_data(avi_t *AVI, char *data, unsigned long length, int audio, int keyframe){ int n = 0; unsigned char astr[5]; // transcode core itself checks for the size -- unneeded and // does harm to xvid 2pass encodes where the first pass can get // _very_ large -- tibit. #if 0 /* Check for maximum file length */ if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN ) { AVI_errno = AVI_ERR_SIZELIM; return -1; }#endif /* Add index entry */ //set tag for current audio track sprintf((char *)astr, "0%1dwb", (int)(AVI->aptr+1)); if(audio) { if (!AVI->is_opendml) n = avi_add_index_entry(AVI,astr,0x10,AVI->pos,length); n += avi_add_odml_index_entry(AVI,astr,0x10,AVI->pos,length); } else { if (!AVI->is_opendml) n = avi_add_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); n += avi_add_odml_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); } if(n) return -1; /* Output tag and data */ if(audio) n = avi_add_chunk(AVI,(unsigned char *)astr, (unsigned char *)data, length); else n = avi_add_chunk(AVI,(unsigned char *)"00db", (unsigned char *)data, length); if (n) return -1; return 0;}GF_EXPORTint AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe){ s64 pos; if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } pos = AVI->pos; if(avi_write_data(AVI,data,bytes,0,keyframe)) return -1; AVI->last_pos = pos; AVI->last_len = bytes; AVI->video_frames++; return 0;}int AVI_dup_frame(avi_t *AVI){ if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if(AVI->last_pos==0) return 0; /* No previous real frame */ if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,AVI->last_pos,AVI->last_len)) return -1; AVI->video_frames++; AVI->must_use_index = 1; return 0;}int AVI_write_audio(avi_t *AVI, char *data, long bytes){ if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } if( avi_write_data(AVI,data,bytes,1,0) ) return -1; AVI->track[AVI->aptr].audio_bytes += bytes; AVI->track[AVI->aptr].audio_chunks++; return 0;}int AVI_append_audio(avi_t *AVI, char *data, long bytes){ // won't work for >2gb long i, length, pos; unsigned char c[4]; if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } // update last index entry: --AVI->n_idx; length = str2ulong(AVI->idx[AVI->n_idx]+12); pos = str2ulong(AVI->idx[AVI->n_idx]+8); //update; long2str(AVI->idx[AVI->n_idx]+12,length+bytes); ++AVI->n_idx; AVI->track[AVI->aptr].audio_bytes += bytes; //update chunk header gf_f64_seek(AVI->fdes, pos+4, SEEK_SET); long2str(c, length+bytes); avi_write(AVI->fdes, (char *)c, 4); gf_f64_seek(AVI->fdes, pos+8+length, SEEK_SET); i=PAD_EVEN(length + bytes); bytes = i - length; avi_write(AVI->fdes, data, bytes); AVI->pos = pos + 8 + i; return 0;}u64 AVI_bytes_remain(avi_t *AVI){ if(AVI->mode==AVI_MODE_READ) return 0; return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx));}u64 AVI_bytes_written(avi_t *AVI){ if(AVI->mode==AVI_MODE_READ) return 0; return (AVI->pos + 8 + 16*AVI->n_idx);}int AVI_set_audio_track(avi_t *AVI, u32 track){ if (track + 1 > AVI->anum) return(-1); //this info is not written to file anyway AVI->aptr=track; return 0;}int AVI_get_audio_track(avi_t *AVI){ return(AVI->aptr);}void AVI_set_audio_vbr(avi_t *AVI, long is_vbr){ AVI->track[AVI->aptr].a_vbr = is_vbr;}long AVI_get_audio_vbr(avi_t *AVI){ return(AVI->track[AVI->aptr].a_vbr);}/******************************************************************* * * * Utilities for reading video and audio from an AVI File * * * *******************************************************************/GF_EXPORTint AVI_close(avi_t *AVI){ int ret; u32 j;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -