📄 aviheader.c
字号:
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(verbose>=2) print_index(priv->idx,priv->idx_size); } break; /* added May 2002 */ case mmioFOURCC('R','I','F','F'): { char riff_type[4]; mp_msg(MSGT_HEADER, MSGL_V, "additional RIFF header...\n"); stream_read(demuxer->stream, riff_type, sizeof riff_type); if (strncmp(riff_type, "AVIX", sizeof riff_type)) mp_msg(MSGT_HEADER, MSGL_WARN, "** warning: this is no extended AVI header..\n"); 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%X pos=0x%X chunksize=0x%X next=0x%X\n", (int)list_end, (int)stream_tell(demuxer->stream), chunksize, (int)chunksize+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,"Broken chunk? chunksize=%d (id=%.4s)\n",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); }if (priv->suidx_size > 0 && priv->idx_size == 0) { /* * No NEWAVIINDEX, but we got an OpenDML index. */ priv->isodml = 1;}if (priv->isodml && (index_mode==-1 || index_mode==0)) { int i, j, k; int safety=1000; avisuperindex_chunk *cx; AVIINDEXENTRY *idx; if (priv->idx_size) free(priv->idx); priv->idx_size = 0; priv->idx_offset = 0; priv->idx = NULL; mp_msg(MSGT_HEADER, MSGL_INFO, "AVI: ODML: Building odml index (%d superindexchunks)\n", priv->suidx_size); // read the standard indices for (cx = &priv->suidx[0], i=0; i<priv->suidx_size; cx++, i++) { stream_reset(demuxer->stream); for (j=0; j<cx->nEntriesInUse; j++) { int ret1, ret2; memset(&cx->stdidx[j], 0, 32); ret1 = stream_seek(demuxer->stream, (off_t)cx->aIndex[j].qwOffset); ret2 = stream_read(demuxer->stream, (char *)&cx->stdidx[j], 32); if (ret1 != 1 || ret2 != 32 || cx->stdidx[j].nEntriesInUse==0) { // this is a broken file (probably incomplete) let the standard // gen_index routine handle this priv->isodml = 0; priv->idx_size = 0; mp_msg(MSGT_HEADER, MSGL_WARN, "AVI: ODML: Broken (incomplete?) file detected. Will use traditional index\n"); goto freeout; } le2me_AVISTDIDXCHUNK(&cx->stdidx[j]); print_avistdindex_chunk(&cx->stdidx[j]); priv->idx_size += cx->stdidx[j].nEntriesInUse; cx->stdidx[j].aIndex = malloc(cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry)); stream_read(demuxer->stream, (char *)cx->stdidx[j].aIndex, cx->stdidx[j].nEntriesInUse*sizeof(avistdindex_entry)); for (k=0;k<cx->stdidx[j].nEntriesInUse; k++) le2me_AVISTDIDXENTRY(&cx->stdidx[j].aIndex[k]); cx->stdidx[j].dwReserved3 = 0; } } /* * We convert the index by translating all entries into AVIINDEXENTRYs * and sorting them by offset. The result should be the same index * we would get with -forceidx. */ idx = priv->idx = malloc(priv->idx_size * sizeof (AVIINDEXENTRY)); for (cx = priv->suidx; cx != &priv->suidx[priv->suidx_size]; cx++) { avistdindex_chunk *sic; for (sic = cx->stdidx; sic != &cx->stdidx[cx->nEntriesInUse]; sic++) { avistdindex_entry *sie; for (sie = sic->aIndex; sie != &sic->aIndex[sic->nEntriesInUse]; sie++) { uint64_t off = sic->qwBaseOffset + sie->dwOffset - 8; memcpy(&idx->ckid, sic->dwChunkId, 4); idx->dwChunkOffset = off; idx->dwFlags = (off >> 32) << 16; idx->dwChunkLength = sie->dwSize & 0x7fffffff; idx->dwFlags |= (sie->dwSize&0x80000000)?0x0:AVIIF_KEYFRAME; // bit 31 denotes !keyframe idx++; } } } qsort(priv->idx, priv->idx_size, sizeof(AVIINDEXENTRY), avi_idx_cmp); /* Hack to work around a "wrong" index in some divx odml files (processor_burning.avi as an example) They have ##dc on non keyframes but the ix00 tells us they are ##db. Read the fcc of a non-keyframe vid frame and check it. */ { uint32_t id; uint32_t db = 0; stream_reset (demuxer->stream); // find out the video stream id. I have seen files with 01db. for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){ unsigned char res[2]; if (odml_get_vstream_id(idx->ckid, res)) { db = mmioFOURCC(res[0], res[1], 'd', 'b'); break; } } // find first non keyframe for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){ if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db) break; } if (i<priv->idx_size && db) { stream_seek(demuxer->stream, AVI_IDX_OFFSET(idx)); id = stream_read_dword_le(demuxer->stream); if (id && id != db) // index fcc and real fcc differ? fix it. for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; i<priv->idx_size; i++, idx++){ if (!(idx->dwFlags & AVIIF_KEYFRAME) && idx->ckid == db) idx->ckid = id; } } } if (verbose>=2) print_index(priv->idx, priv->idx_size); demuxer->movi_end=demuxer->stream->end_pos;freeout: // free unneeded stuff cx = &priv->suidx[0]; do { for (j=0;j<cx->nEntriesInUse;j++) if (cx->stdidx[j].nEntriesInUse) free(cx->stdidx[j].aIndex); free(cx->stdidx); } while (cx++ != &priv->suidx[priv->suidx_size-1]); free(priv->suidx);}/* Read a saved index file */if (index_file_load) { FILE *fp; char magic[7]; unsigned int i; if ((fp = fopen(index_file_load, "r")) == NULL) { mp_msg(MSGT_HEADER,MSGL_ERR, "Can't read index file %s: %s\n", index_file_load, strerror(errno)); goto gen_index; } fread(&magic, 6, 1, fp); if (strncmp(magic, "MPIDX1", 6)) { mp_msg(MSGT_HEADER,MSGL_ERR, "%s is not a valid MPlayer index file\n", index_file_load); goto gen_index; } fread(&priv->idx_size, sizeof(priv->idx_size), 1, fp); priv->idx=malloc(priv->idx_size*sizeof(AVIINDEXENTRY)); if (!priv->idx) { mp_msg(MSGT_HEADER,MSGL_ERR, "Could not allocate memory for index data from %s\n", index_file_load); priv->idx_size = 0; goto gen_index; } for (i=0; i<priv->idx_size;i++) { AVIINDEXENTRY *idx; idx=&((AVIINDEXENTRY *)priv->idx)[i]; fread(idx, sizeof(AVIINDEXENTRY), 1, fp); if (feof(fp)) { mp_msg(MSGT_HEADER,MSGL_ERR, "Premature end of index file %s\n", index_file_load); free(priv->idx); priv->idx_size = 0; goto gen_index; } } fclose(fp); mp_msg(MSGT_HEADER,MSGL_INFO, "Loaded index file: %s\n", index_file_load);}gen_index:if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){ // build index for file: stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); priv->idx_pos=0; priv->idx_size=0; priv->idx=NULL; while(1){ int id; unsigned len; off_t skip; AVIINDEXENTRY* idx; unsigned int c; demuxer->filepos=stream_tell(demuxer->stream); if(demuxer->filepos>=demuxer->movi_end && demuxer->movi_start<demuxer->movi_end) break; id=stream_read_dword_le(demuxer->stream); len=stream_read_dword_le(demuxer->stream); if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){ id=stream_read_dword_le(demuxer->stream); // list or RIFF type continue; } if(stream_eof(demuxer->stream)) break; if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?) if(priv->idx_pos>=priv->idx_size){// priv->idx_size+=32; priv->idx_size+=1024; // +16kB priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY)); if(!priv->idx){priv->idx_pos=0; break;} // error! } idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++]; idx->ckid=id; idx->dwFlags=AVIIF_KEYFRAME; // FIXME idx->dwFlags|=(demuxer->filepos>>16)&0xffff0000U; idx->dwChunkOffset=(unsigned long)demuxer->filepos; idx->dwChunkLength=len; c=stream_read_dword(demuxer->stream); // Fix keyframes for DivX files: if(idxfix_divx) if(avi_stream_id(id)==idxfix_videostream){ switch(idxfix_divx){ case 3: c=stream_read_dword(demuxer->stream)<<5; //skip 32+5 bits for m$mpeg4v1 case 1: if(c&0x40000000) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 3 case 2: if(c==0x1B6) idx->dwFlags&=~AVIIF_KEYFRAME;break; // divx 4 } } // update status line: { static off_t lastpos; off_t pos; off_t len=demuxer->movi_end-demuxer->movi_start; if(len){ pos=100*(demuxer->filepos-demuxer->movi_start)/len; // % } else { pos=(demuxer->filepos-demuxer->movi_start)>>20; // MB } if(pos!=lastpos){ lastpos=pos; mp_msg(MSGT_HEADER,MSGL_STATUS,"Generating Index: %3lu %s \r", (unsigned long)pos, len?"%":"MB"); } } mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %08X %X\n",(unsigned int)demuxer->filepos,id,(char *) &id,(int)c,(unsigned int) idx->dwFlags);#if 0 { unsigned char tmp[64]; int i; stream_read(demuxer->stream,tmp,64); printf("%.4s",&id); for(i=0;i<64;i++) printf(" %02X",tmp[i]); printf("\n"); }#endifskip_chunk: skip=(len+1)&(~1UL); // total bytes in this chunk stream_seek(demuxer->stream,8+demuxer->filepos+skip); } priv->idx_size=priv->idx_pos; mp_msg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size); if(verbose>=2) print_index(priv->idx,priv->idx_size); /* Write generated index to a file */ if (index_file_save) { FILE *fp; unsigned int i; if ((fp=fopen(index_file_save, "w")) == NULL) { mp_msg(MSGT_HEADER,MSGL_ERR, "Couldn't write index file %s: %s\n", index_file_save, strerror(errno)); return; } fwrite("MPIDX1", 6, 1, fp); fwrite(&priv->idx_size, sizeof(priv->idx_size), 1, fp); for (i=0; i<priv->idx_size; i++) { AVIINDEXENTRY *idx = &((AVIINDEXENTRY *)priv->idx)[i]; fwrite(idx, sizeof(AVIINDEXENTRY), 1, fp); } fclose(fp); mp_msg(MSGT_HEADER,MSGL_INFO, "Saved index file: %s\n", index_file_save); }}}#undef MIN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -