📄 muxer_avi.c
字号:
muxer->avih.dwFlags|=AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE; muxer->avih.dwTotalFrames=0; for (i=0; i<muxer->idx_pos; i++) { if (muxer->idx[i].ckid == muxer->def_v->ckid) muxer->avih.dwTotalFrames++; }// muxer->avih.dwSuggestedBufferSize=muxer->def_v->h.dwSuggestedBufferSize; muxer->avih.dwWidth=muxer->def_v->bih->biWidth; muxer->avih.dwHeight=muxer->def_v->bih->biHeight; } // AVI header: hdrsize=sizeof(muxer->avih)+8; if (isodml) hdrsize+=sizeof(dmlh)+20; // dmlh // calc total header size: for(i=0;i<muxer->avih.dwStreams;i++){ muxer_stream_t *s = muxer->streams[i]; struct avi_stream_info *si = s->priv; hdrsize+=12; // LIST hdrsize+=sizeof(muxer->streams[i]->h)+8; // strh switch(muxer->streams[i]->type){ case MUXER_TYPE_VIDEO: hdrsize+=muxer->streams[i]->bih->biSize+8; // strf if (aspect != 0) { hdrsize+=8+4*(9+8*1); // vprp } break; case MUXER_TYPE_AUDIO: hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf break; } if (isodml && si && si->superidx && si->superidxsize) { hdrsize += 32 + 16*si->superidxsize; //indx } } write_avi_list(f,listtypeAVIHEADER,hdrsize); le2me_MainAVIHeader(&muxer->avih); write_avi_chunk(f,ckidAVIMAINHDR,sizeof(muxer->avih),&muxer->avih); /* MainAVIHeader */ le2me_MainAVIHeader(&muxer->avih); // stream headers: for(i=0;i<muxer->avih.dwStreams;i++){ muxer_stream_t *s = muxer->streams[i]; struct avi_stream_info *si = s->priv; unsigned int idxhdr[8]; int j,n; hdrsize=sizeof(s->h)+8; // strh if (si && si->superidx && si->superidxsize) { hdrsize += 32 + 16*si->superidxsize; //indx } switch(s->type){ case MUXER_TYPE_VIDEO: hdrsize+=s->bih->biSize+8; // strf s->h.fccHandler = s->bih->biCompression; s->h.rcFrame.right = s->bih->biWidth; s->h.rcFrame.bottom = s->bih->biHeight; if (aspect != 0) { // fill out vprp info memset(&vprp, 0, sizeof(vprp)); vprp.dwVerticalRefreshRate = (s->h.dwRate+s->h.dwScale-1)/s->h.dwScale; vprp.dwHTotalInT = muxer->avih.dwWidth; vprp.dwVTotalInLines = muxer->avih.dwHeight; vprp.dwFrameAspectRatio = aspect; vprp.dwFrameWidthInPixels = muxer->avih.dwWidth; vprp.dwFrameHeightInLines = muxer->avih.dwHeight; vprp.nbFieldPerFrame = 1; vprp.FieldInfo[0].CompressedBMHeight = muxer->avih.dwHeight; vprp.FieldInfo[0].CompressedBMWidth = muxer->avih.dwWidth; vprp.FieldInfo[0].ValidBMHeight = muxer->avih.dwHeight; vprp.FieldInfo[0].ValidBMWidth = muxer->avih.dwWidth; hdrsize+=8+4*(9+8*1); // vprp } break; case MUXER_TYPE_AUDIO: hdrsize+=WFSIZE(s->wf)+8; // strf s->h.fccHandler = s->wf->wFormatTag; break; } write_avi_list(f,listtypeSTREAMHEADER,hdrsize); le2me_AVIStreamHeader(&s->h); write_avi_chunk(f,ckidSTREAMHEADER,sizeof(s->h),&s->h); /* AVISTreamHeader */ // strh le2me_AVIStreamHeader(&s->h); switch(s->type){ case MUXER_TYPE_VIDEO:{ int biSize=s->bih->biSize; le2me_BITMAPINFOHEADER(s->bih); write_avi_chunk(f,ckidSTREAMFORMAT,biSize,s->bih); /* BITMAPINFOHEADER */ le2me_BITMAPINFOHEADER(s->bih); if (aspect != 0) { int fields = vprp.nbFieldPerFrame; le2me_VideoPropHeader(&vprp); le2me_VIDEO_FIELD_DESC(&vprp.FieldInfo[0]); le2me_VIDEO_FIELD_DESC(&vprp.FieldInfo[1]); write_avi_chunk(f,mmioFOURCC('v','p','r','p'), sizeof(VideoPropHeader) - sizeof(VIDEO_FIELD_DESC)*(2-fields), &vprp); /* Video Properties Header */ }} break; case MUXER_TYPE_AUDIO:{ int wfsize = WFSIZE(s->wf); le2me_WAVEFORMATEX(s->wf); write_avi_chunk(f,ckidSTREAMFORMAT,wfsize,s->wf); /* WAVEFORMATEX */ le2me_WAVEFORMATEX(s->wf);} break; } if (isodml && si && si->superidx && si->superidxsize) { n = si->superidxsize; idxhdr[0] = le2me_32(mmioFOURCC('i', 'n', 'd', 'x')); idxhdr[1] = le2me_32(24 + 16*n); idxhdr[2] = le2me_32(0x00000004); idxhdr[3] = le2me_32(si->superidxpos); idxhdr[4] = le2me_32(s->ckid); idxhdr[5] = 0; idxhdr[6] = 0; idxhdr[7] = 0; fwrite(idxhdr,sizeof(idxhdr),1,f); for (j=0; j<n; j++) { struct avi_odmlsuperidx_entry *entry = &si->superidx[j]; unsigned int data[4]; data[0] = le2me_32(entry->ofs); data[1] = le2me_32(entry->ofs >> 32); data[2] = le2me_32(entry->len); data[3] = le2me_32(entry->duration); fwrite(data,sizeof(data),1,f); } } } // ODML if (isodml) { memset(dmlh, 0, sizeof(dmlh)); dmlh[0] = le2me_32(muxer->avih.dwTotalFrames); write_avi_list(f,mmioFOURCC('o','d','m','l'),sizeof(dmlh)+8); write_avi_chunk(f,mmioFOURCC('d','m','l','h'),sizeof(dmlh),dmlh); }// ============= INFO ===============// always include software infoinfo[0].id=mmioFOURCC('I','S','F','T'); // Software:info[0].text="MEncoder " VERSION;// include any optional stringsi=1;if(info_name!=NULL){ info[i].id=mmioFOURCC('I','N','A','M'); // Name: info[i++].text=info_name;}if(info_artist!=NULL){ info[i].id=mmioFOURCC('I','A','R','T'); // Artist: info[i++].text=info_artist;}if(info_genre!=NULL){ info[i].id=mmioFOURCC('I','G','N','R'); // Genre: info[i++].text=info_genre;}if(info_subject!=NULL){ info[i].id=mmioFOURCC('I','S','B','J'); // Subject: info[i++].text=info_subject;}if(info_copyright!=NULL){ info[i].id=mmioFOURCC('I','C','O','P'); // Copyright: info[i++].text=info_copyright;}if(info_sourceform!=NULL){ info[i].id=mmioFOURCC('I','S','R','F'); // Source Form: info[i++].text=info_sourceform;}if(info_comment!=NULL){ info[i].id=mmioFOURCC('I','C','M','T'); // Comment: info[i++].text=info_comment;}info[i].id=0; hdrsize=0; // calc info size: for(i=0;info[i].id!=0;i++) if(info[i].text){ size_t sz=strlen(info[i].text)+1; hdrsize+=sz+8+sz%2; } // write infos: if (hdrsize!=0){ write_avi_list(f,mmioFOURCC('I','N','F','O'),hdrsize); for(i=0;info[i].id!=0;i++) if(info[i].text){ write_avi_chunk(f,info[i].id,strlen(info[i].text)+1,info[i].text); } } // JUNK: write_avi_chunk(f,ckidAVIPADDING,MOVIALIGN-(ftello(f)%MOVIALIGN)-8,NULL); /* junk */ if (!isodml) { // 'movi' header: write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftello(f)-12); } else { if (ftello(f) != MOVIALIGN) { mp_msg(MSGT_MUXER, MSGL_ERR, "Opendml superindex is too big for reserved space!\n"); mp_msg(MSGT_MUXER, MSGL_ERR, "Expected filepos %d, real filepos %d, missing space %d\n", MOVIALIGN, ftell(muxer->file), ftell(muxer->file)-MOVIALIGN); mp_msg(MSGT_MUXER, MSGL_ERR, "Try increasing MOVIALIGN in libmpdemux/muxer_avi.c\n"); } write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftello(f)-12); } muxer->movi_start=ftello(muxer->file); if (muxer->file_end == 0) muxer->file_end = ftello(muxer->file);}static void avifile_odml_write_index(muxer_t *muxer){ muxer_stream_t* s; struct avi_stream_info *si; int i; for (i=0; i<muxer->avih.dwStreams; i++) { int j,k,n,idxpos,len,last,entries_per_subidx; unsigned int idxhdr[8]; s = muxer->streams[i]; si = s->priv; /* * According to Avery Lee MSMP wants the subidx chunks to have the same size. * * So this code figures out how many entries we can put into * an ix?? chunk, so that each ix?? chunk has the same size and the offsets * don't overflow (Using ODML_CHUNKLEN for that is a bit more restrictive * than it has to be though). */ len = 0; n = 0; entries_per_subidx = INT_MAX; do { off_t start = si->idx[0].ofs; last = entries_per_subidx; for (j=0; j<si->idxpos; j++) { len = si->idx[j].ofs - start; if(len >= ODML_CHUNKLEN || n >= entries_per_subidx) { if (entries_per_subidx > n) { entries_per_subidx = n; } start = si->idx[j].ofs; len = 0; n = 0; } n++; } } while (last != entries_per_subidx); si->superidxpos = (si->idxpos+entries_per_subidx-1) / entries_per_subidx; mp_msg(MSGT_MUXER, MSGL_V, "ODML: Stream %d: Using %d entries per subidx, %d entries in superidx\n", i, entries_per_subidx, si->superidxpos); si->superidxsize = si->superidxpos; si->superidx = malloc(sizeof(*si->superidx) * si->superidxsize); memset(si->superidx, 0, sizeof(*si->superidx) * si->superidxsize); idxpos = 0; for (j=0; j<si->superidxpos; j++) { off_t start = si->idx[idxpos].ofs; int duration; duration = 0; for (k=0; k<entries_per_subidx && idxpos+k<si->idxpos; k++) { duration += s->h.dwSampleSize ? si->idx[idxpos+k].len/s->h.dwSampleSize : 1; } idxhdr[0] = le2me_32((s->ckid << 16) | mmioFOURCC('i', 'x', 0, 0)); idxhdr[1] = le2me_32(24 + 8*k); idxhdr[2] = le2me_32(0x01000002); idxhdr[3] = le2me_32(k); idxhdr[4] = le2me_32(s->ckid); idxhdr[5] = le2me_32(start + 8); idxhdr[6] = le2me_32((start + 8)>> 32); idxhdr[7] = 0; /* unused */ si->superidx[j].len = 32 + 8*k; si->superidx[j].ofs = ftello(muxer->file); si->superidx[j].duration = duration; fwrite(idxhdr,sizeof(idxhdr),1,muxer->file); for (k=0; k<entries_per_subidx && idxpos<si->idxpos; k++) { unsigned int entry[2]; entry[0] = le2me_32(si->idx[idxpos].ofs - start); entry[1] = le2me_32(si->idx[idxpos].len | si->idx[idxpos].flags); idxpos++; fwrite(entry,sizeof(entry),1,muxer->file); } } } muxer->file_end=ftello(muxer->file);}static void avifile_write_standard_index(muxer_t *muxer){ muxer->movi_end=ftello(muxer->file); if(muxer->idx && muxer->idx_pos>0){ int i; // fixup index entries:// for(i=0;i<muxer->idx_pos;i++) muxer->idx[i].dwChunkOffset-=muxer->movi_start-4; // write index chunk: for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); write_avi_chunk(muxer->file,ckidAVINEWINDEX,16*muxer->idx_pos,muxer->idx); /* AVIINDEXENTRY */ for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); muxer->avih.dwFlags|=AVIF_HASINDEX; } muxer->file_end=ftello(muxer->file);}static void avifile_write_index(muxer_t *muxer){ struct avi_stream_info *vsi = muxer->def_v->priv; if (vsi->riffofspos > 0){ avifile_odml_write_index(muxer); } else { avifile_write_standard_index(muxer); }}int muxer_init_muxer_avi(muxer_t *muxer){ muxer->cont_new_stream = &avifile_new_stream; muxer->cont_write_chunk = &avifile_write_chunk; muxer->cont_write_header = &avifile_write_header; muxer->cont_write_index = &avifile_write_index; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -