📄 demux_mov.c
字号:
trak->keyframes=malloc(sizeof(unsigned int)*entries); for (i=0;i<entries;i++) trak->keyframes[i]=stream_read_dword(demuxer->stream)-1;// for (i=0;i<entries;i++) printf("%3d: %d\n",i,trak->keyframes[i]); break; } case MOV_FOURCC('m','d','i','a'): { mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia stream!\n",level,""); lschunks(demuxer,level+1,pos+len,trak); break; } case MOV_FOURCC('m','i','n','f'): { mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia info!\n",level,""); lschunks(demuxer,level+1,pos+len,trak); break; } case MOV_FOURCC('s','t','b','l'): { mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample info!\n",level,""); lschunks(demuxer,level+1,pos+len,trak); break; } case MOV_FOURCC('e','d','t','s'): { mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sEdit atom!\n", level, ""); lschunks(demuxer,level+1,pos+len,trak); break; } case MOV_FOURCC('e','l','s','t'): { int temp=stream_read_dword(demuxer->stream); int entries=stream_read_dword(demuxer->stream); int ver = (temp << 24); int flags = (temp << 16)|(temp<<8)|temp; int i; mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sEdit list table (%d entries) (ver:%d,flags:%ld)\n", level, "",entries, ver, flags);#if 1 trak->editlist_size=entries; trak->editlist=malloc(trak->editlist_size*sizeof(mov_editlist_t)); for (i=0;i<entries;i++) { int dur=stream_read_dword(demuxer->stream); int mt=stream_read_dword(demuxer->stream); int mr=stream_read_dword(demuxer->stream); // 16.16fp trak->editlist[i].dur=dur; trak->editlist[i].pos=mt; trak->editlist[i].speed=mr; mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n",level,"", i, dur,mt,(float)mr/65536.0f); }#endif break; } case MOV_FOURCC('c','o','d','e'): { /* XXX: Implement atom 'code' for FLASH support */ } default: id = be2me_32(id); mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",&id,(int)len); break; }//switch(id) } else { /* not in track */ switch(id) { case MOV_FOURCC('m','v','h','d'): { stream_skip(demuxer->stream,12); priv->timescale=stream_read_dword(demuxer->stream); priv->duration=stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, (int)priv->timescale,(int)priv->duration); break; } case MOV_FOURCC('t','r','a','k'): {// if(trak) printf("MOV: Warning! trak in trak?\n"); if(priv->track_db>=MOV_MAX_TRACKS){ mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk); return; } if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_INFO, "--------------\n"); trak=malloc(sizeof(mov_track_t)); memset(trak,0,sizeof(mov_track_t)); mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db); trak->id=priv->track_db; priv->tracks[priv->track_db]=trak; lschunks(demuxer,level+1,pos+len,trak); mov_build_index(trak,priv->timescale); switch(trak->type){ case MOV_TRAK_AUDIO: {#if 0 struct { int16_t version; // 0 or 1 (version 1 is qt3.0+) int16_t revision; // 0 int32_t vendor_id; // 0 int16_t channels; // 1 or 2 (Mono/Stereo) int16_t samplesize; // 8 or 16 (8Bit/16Bit) int16_t compression_id; // if version 0 then 0 // if version 1 and vbr then -2 else 0 int16_t packet_size; // 0 uint16_t sample_rate; // samplerate (Hz) // qt3.0+ (version == 1) uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet // if 0 below three values are also 0 uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels // (channels * bytes_per_packet) uint32_t bytes_per_sample; // 0 or size of uncompressed sample // if samples_per_packet and bytes_per_packet are constant (CBR) // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) // --- // optional additional atom-based fields // ([int32_t size,int32_t type,some data ],repeat) } my_stdata; #endif sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); sh->format=trak->fourcc; switch( sh->format ) { case 0x726D6173: /* samr */ /* amr narrowband */ trak->samplebytes=sh->samplesize=1; trak->nchannels=sh->channels=1; sh->samplerate=8000; break; case 0x62776173: /* sawb */ /* amr wideband */ trak->samplebytes=sh->samplesize=1; trak->nchannels=sh->channels=1; sh->samplerate=16000; break; default: // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit// XXX: 32bit fixed point numbers (intfp) are only 2 Byte! // short values are usually one byte leftpadded by zero // int values are usually two byte leftpadded by zero // stdata[]:// 8 short version// 10 short revision// 12 int vendor_id// 16 short channels// 18 short samplesize// 20 short compression_id// 22 short packet_size (==0)// 24 intfp sample_rate// (26 short) unknown (==0)// ---- qt3.0+ (version>=1)// 28 int samples_per_packet// 32 int bytes_per_packet// 36 int bytes_per_frame// 40 int bytes_per_sample// there may be additional atoms following at 28 (version 0)// or 44 (version 1), eg. esds atom of .MP4 files // esds atom:// 28 int atom size (bytes of int size, int type and data)// 32 char[4] atom type (fourc charater code -> esds) // 36 char[] atom data (len=size-8) trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; trak->nchannels=sh->channels=char2short(trak->stdata,16); /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, char2short(trak->stdata,24)/trak->durmap[0].dur);*/ sh->samplerate=char2short(trak->stdata,24); if((sh->samplerate < 7000) && trak->durmap) { switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { // TODO: add more cases. case 31: sh->samplerate = 32000; break; case 43: sh->samplerate = 44100; break; case 47: sh->samplerate = 48000; break; default: mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: unable to determine audio samplerate, " "assuming 44.1kHz (got %d)\n", char2short(trak->stdata,24)/trak->durmap[0].dur); sh->samplerate = 44100; } } } mp_msg(MSGT_DEMUX, MSGL_INFO, "Audio bits: %d chans: %d rate: %d\n", sh->samplesize*8,sh->channels,sh->samplerate); if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ mp_msg(MSGT_DEMUX,MSGL_V,"Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", char2int(trak->stdata,28), char2int(trak->stdata,32), char2int(trak->stdata,36), char2int(trak->stdata,40)); if(trak->stdata_len>=44+8){ int len=char2int(trak->stdata,44); int fcc=char2int(trak->stdata,48); // we have extra audio headers!!! printf("Audio extra header: len=%d fcc=0x%X\n",len,fcc); if((len >= 4) && (char2int(trak->stdata,52) >= 12) && (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a')) && (char2int(trak->stdata,52+8) == MOV_FOURCC('a','l','a','c')) && (len >= 36 + char2int(trak->stdata,52))) { sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found alac atom (%d)!\n", sh->codecdata_len); sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); } else { sh->codecdata_len = len-8; sh->codecdata = trak->stdata+44+8; } } } if((trak->stdata[9]==0 || trak->stdata[9]==1) && trak->stdata_len >= 36) { // version 0 with extra atoms int adjust = (trak->stdata[9]==1)?48:0; int atom_len = char2int(trak->stdata,28+adjust); switch(char2int(trak->stdata,32+adjust)) { // atom type case MOV_FOURCC('e','s','d','s'): { mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); if(atom_len > 8) { esds_t esds; if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { sh->i_bps = esds.avgBitrate/8; // printf("######## audio format = %d ########\n",esds.objectTypeId); if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) sh->format=0x55; // .mp3 // dump away the codec specific configuration for the AAC decoder if(esds.decoderConfigLen){ if( (esds.decoderConfig[0]>>3) == 29 ) sh->format = 0x1d61346d; // request multi-channel mp3 decoder sh->codecdata_len = esds.decoderConfigLen; sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); } } mp4_free_esds(&esds); // freeup esds mem#if 0 { FILE* f=fopen("esds.dat","wb"); fwrite(&trak->stdata[36],atom_len-8,1,f); fclose(f); }#endif } } break; case MOV_FOURCC('a','l','a','c'): { mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found alac atom (%d)!\n", atom_len); if(atom_len > 8) { // copy all the atom (not only payload) for lavc alac decoder sh->codecdata_len = atom_len; sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); } } break; default: mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); } } mp_msg(MSGT_DEMUX, MSGL_INFO, "Fourcc: %.4s\n",&trak->fourcc);#if 0 { FILE* f=fopen("stdata.dat","wb"); fwrite(trak->stdata,trak->stdata_len,1,f); fclose(f); } { FILE* f=fopen("tkdata.dat","wb"); fwrite(trak->tkdata,trak->tkdata_len,1,f); fclose(f); }#endif // Emulate WAVEFORMATEX struct: sh->wf=malloc(sizeof(WAVEFORMATEX)); memset(sh->wf,0,sizeof(WAVEFORMATEX)); sh->wf->nChannels=sh->channels; sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; // sh->wf->nSamplesPerSec=trak->timescale; sh->wf->nSamplesPerSec=(trak->stdata[24]<<8)+trak->stdata[25]; if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) /char2int(trak->stdata,28); sh->wf->nBlockAlign=char2int(trak->stdata,36); } else { sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; // workaround for ms11 ima4 if (sh->format == 0x1100736d && trak->stdata_len >= 36) sh->wf->nBlockAlign=char2int(trak->stdata,36); } // Selection:// if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){// // (auto)selected audio track:// demuxer->audio->id=priv->track_db;// demuxer->audio->sh=sh; sh->ds=demuxer->audio;// } break; } case MOV_TRAK_VIDEO: { int i, entry; int flag, start, count_flag, end, palette_count, gray; int hdr_ptr = 76; // the byte just after depth unsigned char *palette_map; sh_video_t* sh=new_sh_video(demuxer,priv->track_db); int depth = trak->stdata[75]|(trak->stdata[74]<<8); sh->format=trak->fourcc;// stdata[]:// 8 short version// 10 short revision// 12 int vendor_id// 16 int temporal_quality// 20 int spatial_quality// 24 short width// 26 short height// 28 int h_dpi// 32 int v_dpi// 36 int 0// 40 short frames_per_sample// 42 char[4] compressor_name// 74 short depth// 76 short color_table_id// additional atoms may follow,// eg esds atom from .MP4 files// 78 int atom size// 82 char[4] atom type// 86 ... atom data { ImageDescription* id=malloc(8+trak->stdata_len); trak->desc=id; id->idSize=8+trak->stdata_len;// id->cType=bswap_32(trak->fourcc); id->cType=le2me_32(trak->fourcc); id->version=char2short(trak->stdata,8); id->revisionLevel=char2short(trak->stdata,10); id->vendor=char2int(trak->stdata,12); id->temporalQuality=char2int(trak->stdata,16); id->spatialQuality=char2int(trak->stdata,20); id->width=char2short(trak->stdata,24); id->height=char2short(trak->stdata,26); id->hRes=char2int(trak->stdata,28); id->vRes=char2int(trak->stdata,32); id->dataSize=char2int(trak->stdata,36); id->frameCount=char2short(trak->stdata,40); memcpy(&id->name,trak->stdata+42,32); id->depth=char2short(trak->stdata,74); id->clutID=char2short(trak->stdata,76); if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); sh->ImageDesc=id;#if 0 { FILE *f=fopen("ImageDescription","wb"); fwrite(id,id->idSize,1,f); fclose(f); }#endif } if(trak->stdata_len >= 86) { // extra atoms found int pos=78; int atom_len; while(pos+8<=trak->stdata_len && (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ switch(char2int(trak->stdata,pos+4)) { // switch atom type case MOV_FOURCC('g','a','m','a'): // intfp with gamma value at which movie was captured // can be used to gamma correct movie display mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('f','i','e','l'): // 2 char-values (8bit int) that specify field handling // see the Apple's QuickTime Fileformat PDF for more info mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unsupported Field-Handling movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('m','j','q','t'): // Motion-JPEG default quantization table
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -