static void avifile_write_header(muxer_t *muxer){ uint32_t riff[3]; unsigned int dmlh[1]; unsigned int i; unsigned int hdrsize; muxer_info_t info[16]; VideoPropHeader vprp; uint32_t aspect = avi_aspect(muxer->def_v); struct avi_stream_info *vsi = muxer->def_v->priv; int isodml = vsi->riffofspos > 0; mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingHeader); if (aspect == 0) { mp_msg(MSGT_MUXER, MSGL_INFO, "ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.\n"); } else { mp_msg(MSGT_MUXER, MSGL_INFO, "ODML: vprp aspect is %d:%d.\n", aspect >> 16, aspect & 0xffff); } /* deal with stream delays */ for (i = 0; muxer->streams[i] && i < MUXER_MAX_STREAMS; ++i) { muxer_stream_t *s = muxer->streams[i]; if (s->type == MUXER_TYPE_AUDIO && muxer->audio_delay_fix > 0.0) { s->h.dwStart = muxer->audio_delay_fix * s->h.dwRate/s->h.dwScale + 0.5; mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_SettingAudioDelay, (float)s->h.dwStart * s->h.dwScale/s->h.dwRate); } if (s->type == MUXER_TYPE_VIDEO && muxer->audio_delay_fix < 0.0) { s->h.dwStart = -muxer->audio_delay_fix * s->h.dwRate/s->h.dwScale + 0.5; mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_SettingVideoDelay, (float)s->h.dwStart * s->h.dwScale/s->h.dwRate); } } if (isodml) { unsigned int rifflen, movilen; int i; vsi->riffofs[vsi->riffofspos+1] = muxer->file_end; /* fixup RIFF lengths */ for (i=0; i<=vsi->riffofspos; i++) { rifflen = vsi->riffofs[i+1] - vsi->riffofs[i] - 8; movilen = le2me_32(rifflen - 12); rifflen = le2me_32(rifflen); stream_seek(muxer->stream, vsi->riffofs[i]+4); stream_write_buffer(muxer->stream,&rifflen,4); /* fixup movi length */ if (i > 0) { stream_seek(muxer->stream, vsi->riffofs[i]+16); stream_write_buffer(muxer->stream,&movilen,4); } } stream_seek(muxer->stream, 12); } else { // RIFF header: riff[0]=mmioFOURCC('R','I','F','F'); riff[1]=muxer->file_end-2*sizeof(unsigned int); // filesize riff[2]=formtypeAVI; // 'AVI ' riff[0]=le2me_32(riff[0]); riff[1]=le2me_32(riff[1]); riff[2]=le2me_32(riff[2]); stream_write_buffer(muxer->stream,&riff,12); } // update AVI header: if(muxer->def_v){ int i; muxer->avih.dwMicroSecPerFrame=1000000.0*muxer->def_v->h.dwScale/muxer->def_v->h.dwRate; // muxer->avih.dwMaxBytesPerSec=1000000; // dummy!!!!! FIXME // muxer->avih.dwPaddingGranularity=2; // ??? 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(muxer->stream,listtypeAVIHEADER,hdrsize); le2me_MainAVIHeader(&muxer->avih); write_avi_chunk(muxer->stream,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(muxer->stream,listtypeSTREAMHEADER,hdrsize); le2me_AVIStreamHeader(&s->h); write_avi_chunk(muxer->stream,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(muxer->stream,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(muxer->stream,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(muxer->stream,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; stream_write_buffer(muxer->stream,idxhdr,sizeof(idxhdr)); 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); stream_write_buffer(muxer->stream,data,sizeof(data)); } } }
void read_avi_header(demuxer_t *demuxer,int index_mode){ sh_audio_t *sh_audio=NULL; sh_video_t *sh_video=NULL; int stream_id=-1; int idxfix_videostream=0; int idxfix_divx=0; avi_priv_t* priv=demuxer->priv; off_t list_end=0; //---- AVI header: priv->idx_size=0; priv->audio_streams=0; while(1){ int id=stream_read_dword_le(demuxer->stream); unsigned chunksize,size2; static int last_fccType=0; static int last_fccHandler=0; char* hdr=NULL; // if(stream_eof(demuxer->stream)) break; // Imply -forceidx if -saveidx is specified if (index_file_save) index_mode = 2; // if(id==mmioFOURCC('L','I','S','T')){ unsigned len=stream_read_dword_le(demuxer->stream); // list size id=stream_read_dword_le(demuxer->stream); // list type mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%u\n",(char *) &id,len); if(len >= 4) { len -= 4; list_end=stream_tell(demuxer->stream)+((len+1)&(~1)); } else { mp_msg(MSGT_HEADER,MSGL_WARN,MSGTR_MPDEMUX_AVIHDR_EmptyList); list_end = 0; } mp_msg(MSGT_HEADER,MSGL_V,"list_end=0x%X\n",(int)list_end); if(id==listtypeAVIMOVIE){ // found MOVI header if(!demuxer->movi_start) demuxer->movi_start=stream_tell(demuxer->stream); demuxer->movi_end=stream_tell(demuxer->stream)+len; mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundMovieAt,(int)demuxer->movi_start,(int)demuxer->movi_end); if(demuxer->stream->end_pos>demuxer->movi_end) demuxer->movi_end=demuxer->stream->end_pos; if(index_mode==-2 || index_mode==2 || index_mode==0) break; // reading from non-seekable source (stdin) or forced index or no index forced if(list_end>0) stream_seek(demuxer->stream,list_end); // skip movi list_end=0; } continue; } size2=stream_read_dword_le(demuxer->stream); mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%u\n",(char *) &id,size2); chunksize=(size2+1)&(~1); switch(id){ // Indicates where the subject of the file is archived case mmioFOURCC('I','A','R','L'): hdr="Archival Location";break; // Lists the artist of the original subject of the file; // for example, "Michaelangelo." case mmioFOURCC('I','A','R','T'): hdr="Artist";break; // Lists the name of the person or organization that commissioned // the subject of the file; for example "Pope Julian II." case mmioFOURCC('I','C','M','S'): hdr="Commissioned";break; // Provides general comments about the file or the subject // of the file. If the comment is several sentences long, end each // sentence with a period. Do not include new-line characters. case mmioFOURCC('I','C','M','T'): hdr="Comments";break; // Records the copyright information for the file; for example, // "Copyright Encyclopedia International 1991." If there are multiple // copyrights, separate them by semicolon followed by a space. case mmioFOURCC('I','C','O','P'): hdr="Copyright";break; // Describes whether an image has been cropped and, if so, how it // was cropped; for example, "lower-right corner." case mmioFOURCC('I','C','R','D'): hdr="Creation Date";break; // Describes whether an image has been cropped and, if so, how it // was cropped; for example, "lower-right corner." case mmioFOURCC('I','C','R','P'): hdr="Cropped";break; // Specifies the size of the original subject of the file; for // example, "8.5 in h, 11 in w." case mmioFOURCC('I','D','I','M'): hdr="Dimensions";break; // Stores dots per inch setting of the digitizer used to // produce the file, such as "300." case mmioFOURCC('I','D','P','I'): hdr="Dots Per Inch";break; // Stores the of the engineer who worked on the file. If there are // multiple engineers, separate the names by a semicolon and a blank; // for example, "Smith, John; Adams, Joe." case mmioFOURCC('I','E','N','G'): hdr="Engineer";break; // Describes the original work, such as "landscape,", "portrait," // "still liefe," etc. case mmioFOURCC('I','G','N','R'): hdr="Genre";break; // Provides a list of keywords that refer to the file or subject of the // file. Separate multiple keywords with a semicolon and a blank; // for example, "Seattle, aerial view; scenery." case mmioFOURCC('I','K','E','Y'): hdr="Keywords";break; // ILGT - Describes the changes in the lightness settings on the digitizer // required to produce the file. Note that the format of this information // depends on the hardware used. case mmioFOURCC('I','L','G','T'): hdr="Lightness";break; // IMED - Decribes the original subject of the file, such as // "computer image," "drawing," "lithograph," and so on. case mmioFOURCC('I','M','E','D'): hdr="Medium";break; // INAM - Stores the title of the subject of the file, such as // "Seattle from Above." case mmioFOURCC('I','N','A','M'): hdr="Title";break; // IPLT - Specifies the number of colors requested when digitizing // an image, such as "256." case mmioFOURCC('I','P','L','T'): hdr="Palette Setting";break; // IPRD - Specifies the name of title the file was originally intended // for, such as "Encyclopedia of Pacific Northwest Geography." case mmioFOURCC('I','P','R','D'): hdr="Product";break; // ISBJ - Decsribes the contents of the file, such as // "Aerial view of Seattle." case mmioFOURCC('I','S','B','J'): hdr="Subject";break; // ISFT - Identifies the name of the software packages used to create the // file, such as "Microsoft WaveEdit" case mmioFOURCC('I','S','F','T'): hdr="Software";break; // ISHP - Identifies the change in sharpness for the digitizer // required to produce the file (the format depends on the hardware used). case mmioFOURCC('I','S','H','P'): hdr="Sharpness";break; // ISRC - Identifies the name of the person or organization who // suplied the original subject of the file; for example, "Try Research." case mmioFOURCC('I','S','R','C'): hdr="Source";break; // ISRF - Identifies the original form of the material that was digitized, // such as "slide," "paper," "map," and so on. This is not necessarily // the same as IMED case mmioFOURCC('I','S','R','F'): hdr="Source Form";break; // ITCH - Identifies the technician who digitized the subject file; // for example, "Smith, John." case mmioFOURCC('I','T','C','H'): hdr="Technician";break; case mmioFOURCC('I','S','M','P'): hdr="Time Code";break; case mmioFOURCC('I','D','I','T'): hdr="Digitization Time";break; case ckidAVIMAINHDR: // read 'avih' stream_read(demuxer->stream,(char*) &avih,FFMIN(size2,sizeof(avih))); le2me_MainAVIHeader(&avih); // swap to machine endian chunksize-=FFMIN(size2,sizeof(avih)); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_avih(&avih,MSGL_V); // else print_avih_flags(&avih,MSGL_V); break; case ckidSTREAMHEADER: { // read 'strh' AVIStreamHeader h; stream_read(demuxer->stream,(char*) &h,FFMIN(size2,sizeof(h))); le2me_AVIStreamHeader(&h); // swap to machine endian chunksize-=FFMIN(size2,sizeof(h)); ++stream_id; if(h.fccType==streamtypeVIDEO){ sh_video=new_sh_video(demuxer,stream_id); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "aviheader", stream_id); memcpy(&sh_video->video,&h,sizeof(h)); sh_video->stream_delay = (float)sh_video->video.dwStart * sh_video->video.dwScale/sh_video->video.dwRate; } else if(h.fccType==streamtypeAUDIO){ sh_audio=new_sh_audio(demuxer,stream_id); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "aviheader", stream_id); memcpy(&sh_audio->audio,&h,sizeof(h)); sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate; } last_fccType=h.fccType; last_fccHandler=h.fccHandler; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_strh(&h,MSGL_V); break; } case mmioFOURCC('i', 'n', 'd', 'x'): { uint32_t i; avisuperindex_chunk *s; if(!index_mode) break; if(chunksize<=24){ break; } priv->suidx_size++; priv->suidx = realloc_struct(priv->suidx, priv->suidx_size, sizeof (avisuperindex_chunk)); s = &priv->suidx[priv->suidx_size-1]; chunksize-=24; memcpy(s->fcc, "indx", 4); s->dwSize = size2; s->wLongsPerEntry = stream_read_word_le(demuxer->stream); s->bIndexSubType = stream_read_char(demuxer->stream); s->bIndexType = stream_read_char(demuxer->stream); s->nEntriesInUse = stream_read_dword_le(demuxer->stream); *(uint32_t *)s->dwChunkId = stream_read_dword_le(demuxer->stream); stream_read(demuxer->stream, (char *)s->dwReserved, 3*4); memset(s->dwReserved, 0, 3*4); print_avisuperindex_chunk(s,MSGL_V); // Check and fix this useless crap if(s->wLongsPerEntry != sizeof (avisuperindex_entry)/4) { mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk size: %u\n",s->wLongsPerEntry); s->wLongsPerEntry = sizeof(avisuperindex_entry)/4; } if( ((chunksize/4)/s->wLongsPerEntry) < s->nEntriesInUse){ mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk\n"); s->nEntriesInUse = (chunksize/4)/s->wLongsPerEntry; } s->aIndex = calloc(s->nEntriesInUse, sizeof (avisuperindex_entry)); s->stdidx = calloc(s->nEntriesInUse, sizeof (avistdindex_chunk)); // now the real index of indices for (i=0; i<s->nEntriesInUse; i++) { chunksize-=16; s->aIndex[i].qwOffset = stream_read_qword_le(demuxer->stream); s->aIndex[i].dwSize = stream_read_dword_le(demuxer->stream); s->aIndex[i].dwDuration = stream_read_dword_le(demuxer->stream); mp_msg (MSGT_HEADER, MSGL_V, "ODML (%.4s): [%d] 0x%016"PRIx64" 0x%04x %u\n", (s->dwChunkId), i, (uint64_t)s->aIndex[i].qwOffset, s->aIndex[i].dwSize, s->aIndex[i].dwDuration); } break; } case ckidSTREAMFORMAT: { // read 'strf' if(last_fccType==streamtypeVIDEO){ sh_video->bih=calloc(FFMAX(chunksize, sizeof(BITMAPINFOHEADER)), 1); // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundBitmapInfoHeader,chunksize,sizeof(BITMAPINFOHEADER)); stream_read(demuxer->stream,(char*) sh_video->bih,chunksize); le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian if (sh_video->bih->biSize > chunksize && sh_video->bih->biSize > sizeof(BITMAPINFOHEADER)) sh_video->bih->biSize = chunksize; // fixup MS-RLE header (seems to be broken for <256 color files) if(sh_video->bih->biCompression<=1 && sh_video->bih->biSize==40) sh_video->bih->biSize=chunksize; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih,MSGL_V); chunksize=0; sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale; sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; sh_video->format = sh_video->bih->biCompression; // if(demuxer->video->id==-1) demuxer->video->id=stream_id; // IdxFix: idxfix_videostream=stream_id; switch(sh_video->bih->biCompression){ case mmioFOURCC('M', 'P', 'G', '4'): case mmioFOURCC('m', 'p', 'g', '4'): case mmioFOURCC('D', 'I', 'V', '1'): idxfix_divx=3; // set index recovery mpeg4 flavour: msmpeg4v1 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPG4V1); break; case mmioFOURCC('D', 'I', 'V', '3'): case mmioFOURCC('d', 'i', 'v', '3'): case mmioFOURCC('D', 'I', 'V', '4'): case mmioFOURCC('d', 'i', 'v', '4'): case mmioFOURCC('D', 'I', 'V', '5'): case mmioFOURCC('d', 'i', 'v', '5'): case mmioFOURCC('D', 'I', 'V', '6'): case mmioFOURCC('d', 'i', 'v', '6'): case mmioFOURCC('M', 'P', '4', '3'): case mmioFOURCC('m', 'p', '4', '3'): case mmioFOURCC('M', 'P', '4', '2'): case mmioFOURCC('m', 'p', '4', '2'): case mmioFOURCC('D', 'I', 'V', '2'): case mmioFOURCC('A', 'P', '4', '1'): idxfix_divx=1; // set index recovery mpeg4 flavour: msmpeg4v3 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForDIVX3); break; case mmioFOURCC('D', 'I', 'V', 'X'): case mmioFOURCC('d', 'i', 'v', 'x'): case mmioFOURCC('D', 'X', '5', '0'): case mmioFOURCC('X', 'V', 'I', 'D'): case mmioFOURCC('x', 'v', 'i', 'd'): case mmioFOURCC('F', 'M', 'P', '4'): case mmioFOURCC('f', 'm', 'p', '4'): idxfix_divx=2; // set index recovery mpeg4 flavour: generic mpeg4 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPEG4); break; } } else if(last_fccType==streamtypeAUDIO){ unsigned wf_size = chunksize<sizeof(WAVEFORMATEX)?sizeof(WAVEFORMATEX):chunksize; sh_audio->wf=calloc(wf_size,1); // sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundWaveFmt,chunksize,sizeof(WAVEFORMATEX)); stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize); le2me_WAVEFORMATEX(sh_audio->wf); if (sh_audio->wf->cbSize != 0 && wf_size < sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize) { sh_audio->wf=realloc(sh_audio->wf, sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize); } sh_audio->format=sh_audio->wf->wFormatTag; if (sh_audio->format == 1 && last_fccHandler == mmioFOURCC('A', 'x', 'a', 'n')) sh_audio->format = last_fccHandler; sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; chunksize=0; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V); ++priv->audio_streams; // if(demuxer->audio->id==-1) demuxer->audio->id=stream_id; } break; } case mmioFOURCC('v', 'p', 'r', 'p'): { VideoPropHeader *vprp = malloc(chunksize); unsigned int i; stream_read(demuxer->stream, (void*)vprp, chunksize); le2me_VideoPropHeader(vprp); chunksize -= sizeof(*vprp)-sizeof(vprp->FieldInfo); chunksize /= sizeof(VIDEO_FIELD_DESC); if (vprp->nbFieldPerFrame > chunksize) { vprp->nbFieldPerFrame = chunksize; } chunksize = 0; for (i=0; i<vprp->nbFieldPerFrame; i++) { le2me_VIDEO_FIELD_DESC(&vprp->FieldInfo[i]); } if (sh_video) { sh_video->aspect = GET_AVI_ASPECT(vprp->dwFrameAspectRatio); } if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_vprp(vprp,MSGL_V); free(vprp); break; } case mmioFOURCC('d', 'm', 'l', 'h'): { // dmlh 00 00 00 04 frms unsigned int total_frames = stream_read_dword_le(demuxer->stream); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundAVIV2Header, chunksize, total_frames); stream_skip(demuxer->stream, chunksize-4); chunksize = 0; } break; case ckidAVINEWINDEX: if(demuxer->movi_end>stream_tell(demuxer->stream)) demuxer->movi_end=stream_tell(demuxer->stream); // fixup movi-end if(index_mode && !priv->isodml){ int i; priv->idx_size=size2>>4; mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_ReadingIndexBlockChunksForFrames, priv->idx_size,avih.dwTotalFrames, (int64_t)stream_tell(demuxer->stream)); priv->idx=malloc(priv->idx_size<<4); // printf("\nindex to %p !!!!! (priv=%p)\n",priv->idx,priv); stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4); for (i = 0; i < priv->idx_size; i++) { // swap index to machine endian AVIINDEXENTRY *entry=(AVIINDEXENTRY*)priv->idx + i; le2me_AVIINDEXENTRY(entry); /* * We (ab)use the upper word for bits 32-47 of the offset, so * we'll clear them here. * FIXME: AFAIK no codec uses them, but if one does it will break */ entry->dwFlags&=0xffff; } chunksize-=priv->idx_size<<4; if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2); } break; /* added May 2002 */ case mmioFOURCC('R','I','F','F'): { char riff_type[4]; mp_msg(MSGT_HEADER, MSGL_V, MSGTR_MPDEMUX_AVIHDR_AdditionalRIFFHdr); stream_read(demuxer->stream, riff_type, sizeof riff_type); if (strncmp(riff_type, "AVIX", sizeof riff_type)) mp_msg(MSGT_HEADER, MSGL_WARN, MSGTR_MPDEMUX_AVIHDR_WarnNotExtendedAVIHdr); else { /* * We got an extended AVI header, so we need to switch to * ODML to get seeking to work, provided we got indx chunks * in the header (suidx_size > 0). */ if (priv->suidx_size > 0) priv->isodml = 1; } chunksize = 0; list_end = 0; /* a new list will follow */ break; } case ckidAVIPADDING: stream_skip(demuxer->stream, chunksize); chunksize = 0; break; } if(hdr){ mp_msg(MSGT_HEADER,MSGL_V,"hdr=%s size=%u\n",hdr,size2); if(size2==3) chunksize=1; // empty else { char buf[256]; int len=(size2<250)?size2:250; stream_read(demuxer->stream,buf,len); chunksize-=len; buf[len]=0; mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf); demux_info_add(demuxer, hdr, buf); } } mp_msg(MSGT_HEADER,MSGL_DBG2,"list_end=0x%"PRIX64" pos=0x%"PRIX64" chunksize=0x%"PRIX64" next=0x%"PRIX64"\n", (int64_t)list_end, (int64_t)stream_tell(demuxer->stream), (int64_t)chunksize, (int64_t)chunksize+(int64_t)stream_tell(demuxer->stream)); if(list_end>0 && chunksize+stream_tell(demuxer->stream) == list_end) list_end=0; if(list_end>0 && chunksize+stream_tell(demuxer->stream)>list_end){ mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_BrokenChunk,chunksize,(char *) &id); stream_seek(demuxer->stream,list_end); list_end=0; } else if(chunksize>0) stream_skip(demuxer->stream,chunksize); else if((int)chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%u (id=%.4s)\n",chunksize,(char *) &id); }