demux_mov.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,854 行 · 第 1/5 页
C
1,854 行
break; case MOV_FOURCC('M','4','P',' '): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n"); break; case MOV_FOURCC('q','t',' ',' '): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Original QuickTime\n"); break; case MOV_FOURCC('3','g','p','1'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 1\n"); break; case MOV_FOURCC('3','g','p','2'): case MOV_FOURCC('3','g','2','a'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 2\n"); break; case MOV_FOURCC('3','g','p','3'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 3\n"); break; case MOV_FOURCC('3','g','p','4'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 4\n"); break; case MOV_FOURCC('3','g','p','5'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: 3GPP Profile 5\n"); break; case MOV_FOURCC('m','m','p','4'): mp_msg(MSGT_DEMUX,MSGL_INFO,"ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n"); break; default: tmp = be2me_32(tmp); mp_msg(MSGT_DEMUX,MSGL_WARN,"ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp); } mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Minor Version: %d\n", stream_read_dword(demuxer->stream)); skipped += 8; // List all compatible brands for(i = 0; i < ((len-16)/4); i++) { tmp = be2me_32(stream_read_dword(demuxer->stream)); mp_msg(MSGT_DEMUX,MSGL_V,"ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp); skipped += 4; }#endif } break; case MOV_FOURCC('m','o','o','v'):// case MOV_FOURCC('c','m','o','v'): mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n"); priv->moov_start=(off_t)stream_tell(demuxer->stream); priv->moov_end=(off_t)priv->moov_start+len-skipped; mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n", (int64_t)priv->moov_start, (int64_t)priv->moov_end); skipped+=8; i = stream_read_dword(demuxer->stream)-8; if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){ skipped+=i; mp_msg(MSGT_DEMUX,MSGL_INFO,"MOV: Reference Media file!!!\n"); //set demuxer type to playlist ... demuxer->type=DEMUXER_TYPE_PLAYLIST; while(i>0){ int len=stream_read_dword(demuxer->stream)-8; int fcc=stream_read_dword(demuxer->stream); if(len<0) break; // EOF!? i-=8;// printf("i=%d len=%d\n",i,len); switch(fcc){ case MOV_FOURCC('r','m','d','a'): continue; case MOV_FOURCC('r','d','r','f'): { int tmp=stream_read_dword(demuxer->stream); int type=stream_read_dword_le(demuxer->stream); int slen=stream_read_dword(demuxer->stream); //char* s=malloc(slen+1); //stream_read(demuxer->stream,s,slen); //FIXME: also store type & data_rate ? ds_read_packet(demuxer->video, demuxer->stream, slen, 0, stream_tell(demuxer->stream), 0 // no flags ); flags|=4; mp_msg(MSGT_DEMUX,MSGL_V,"Added reference to playlist\n"); //s[slen]=0; //mp_msg(MSGT_DEMUX,MSGL_INFO,"REF: [%.4s] %s\n",&type,s); len-=12+slen;i-=12+slen; break; } case MOV_FOURCC('r','m','d','r'): { int flags=stream_read_dword(demuxer->stream); int rate=stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V," min. data rate: %d bits/sec\n",rate); len-=8; i-=8; break; } case MOV_FOURCC('r','m','q','u'): { int q=stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V," quality index: %d\n",q); len-=4; i-=4; break; } } i-=len;stream_skip(demuxer->stream,len); } } flags|=1; break; case MOV_FOURCC('w','i','d','e'): mp_msg(MSGT_DEMUX,MSGL_V,"MOV: 'WIDE' chunk found!\n"); if(flags&2) break; case MOV_FOURCC('m','d','a','t'): mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n"); priv->mdat_start=stream_tell(demuxer->stream); priv->mdat_end=priv->mdat_start+len-skipped; mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n", (int64_t)priv->mdat_start, (int64_t)priv->mdat_end); flags|=2; if(flags==3){ // if we're over the headers, then we can stop parsing here! demuxer->priv=priv; return DEMUXER_TYPE_MOV; } break; case MOV_FOURCC('f','r','e','e'): case MOV_FOURCC('s','k','i','p'): case MOV_FOURCC('j','u','n','k'): mp_msg(MSGT_DEMUX,MSGL_DBG2,"MOV: free space (len: %"PRId64")\n", (int64_t)len); /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */ break; case MOV_FOURCC('p','n','o','t'): case MOV_FOURCC('P','I','C','T'): /* dunno what, but we shoudl ignore it */ break; default: if(no==0){ free(priv); return 0;} // first chunk is bad! id = be2me_32(id); mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); }//skip_chunk: if(!stream_skip(demuxer->stream,len-skipped)) break; ++no; } if(flags==3){ demuxer->priv=priv; return DEMUXER_TYPE_MOV; } free(priv); if ((flags==5) || (flags==7)) // reference & header sent return DEMUXER_TYPE_PLAYLIST; if(flags==1) mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing data (mdat) chunk! Maybe broken file...\n"); else if(flags==2) mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); return 0;}static void demux_close_mov(demuxer_t *demuxer) { mov_priv_t* priv = demuxer->priv; int i; if (!priv) return; for (i = 0; i < MOV_MAX_TRACKS; i++) { mov_track_t *track = priv->tracks[i]; if (track) { free(track->tkdata); free(track->stdata); free(track->stream_header); free(track->samples); free(track->chunks); free(track->chunkmap); free(track->durmap); free(track->keyframes); free(track->editlist); free(track->desc); free(track); } } free(priv);}unsigned int store_ughvlc(unsigned char *s, unsigned int v){ unsigned int n = 0; while(v >= 0xff) { *s++ = 0xff; v -= 0xff; n++; } *s = v; n++; return n;}static void init_vobsub(sh_sub_t *sh, mov_track_t *trak) { int i; uint8_t *pal = trak->stdata; sh->type = 'v'; if (trak->stdata_len < 106) return; sh->has_palette = 1; pal += 42; for (i = 0; i < 16; i++) { sh->palette[i] = BE_32(pal); pal += 4; }}static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, off_t pos, off_t len, mov_track_t* trak);static int gen_sh_audio(sh_audio_t* sh, mov_track_t* trak, int timescale) {#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 int version, adjust; int is_vorbis = 0; sh->format=trak->fourcc; // crude audio delay from editlist0 hack ::atm if(trak->editlist_size>=1) { if(trak->editlist[0].pos == -1) { sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale; mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); } } 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)// TODO: fix parsing for files using version 2. version=char2short(trak->stdata,8); if (version > 1) mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: version %d sound atom may not parse correctly!\n", version); trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; /* I can't find documentation, but so far this is the case. -Corey */ switch (char2short(trak->stdata,16)) { case 1: trak->nchannels = 1; break; case 2: trak->nchannels = 2; break; case 3: trak->nchannels = 6; break; default: mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: unable to determine audio channels, assuming 2 (got %d)\n", char2short(trak->stdata,16)); trak->nchannels = 2; } sh->channels = trak->nchannels; /*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 && trak->durmap[0].dur > 1) { 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_V, "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!!! mp_msg(MSGT_DEMUX,MSGL_V,"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'))) { switch(char2int(trak->stdata,52+8)) { case MOV_FOURCC('a','l','a','c'): if (len >= 36 + char2int(trak->stdata,52)) { sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", sh->codecdata_len); sh->codecdata = malloc(sh->codecdata_len); sh->codecdatatype = 1; memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); } break; case MOV_FOURCC('i','n','2','4'): case MOV_FOURCC('i','n','3','2'): case MOV_FOURCC('f','l','3','2'): case MOV_FOURCC('f','l','6','4'): if ((len >= 22) && (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && (char2short(trak->stdata,52+20))) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?