📄 demux_mov.c
字号:
case MOV_FOURCC(0xa9,'f','m','t'): case MOV_FOURCC(0xa9,'i','n','f'): case MOV_FOURCC(0xa9,'p','r','d'): case MOV_FOURCC(0xa9,'p','r','f'): case MOV_FOURCC(0xa9,'r','e','q'): case MOV_FOURCC(0xa9,'s','r','c'): case MOV_FOURCC('n','a','m','e'): case MOV_FOURCC(0xa9,'n','a','m'): case MOV_FOURCC(0xa9,'A','R','T'): case MOV_FOURCC(0xa9,'c','m','t'): case MOV_FOURCC(0xa9,'a','u','t'): case MOV_FOURCC(0xa9,'s','w','r'): { off_t text_len = stream_read_word(demuxer->stream); char text[text_len+2+1]; stream_read(demuxer->stream, (char *)&text, text_len+2); text[text_len+2] = 0x0; switch(udta_id) { case MOV_FOURCC(0xa9,'a','u','t'): demux_info_add(demuxer, "author", &text[2]); mp_msg(MSGT_DEMUX, MSGL_V, " Author: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'c','p','y'): demux_info_add(demuxer, "copyright", &text[2]); mp_msg(MSGT_DEMUX, MSGL_V, " Copyright: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'i','n','f'): mp_msg(MSGT_DEMUX, MSGL_V, " Info: %s\n", &text[2]); break; case MOV_FOURCC('n','a','m','e'): case MOV_FOURCC(0xa9,'n','a','m'): demux_info_add(demuxer, "name", &text[2]); mp_msg(MSGT_DEMUX, MSGL_V, " Name: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'A','R','T'): mp_msg(MSGT_DEMUX, MSGL_V, " Artist: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'d','i','r'): mp_msg(MSGT_DEMUX, MSGL_V, " Director: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'c','m','t'): demux_info_add(demuxer, "comments", &text[2]); mp_msg(MSGT_DEMUX, MSGL_V, " Comment: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'r','e','q'): mp_msg(MSGT_DEMUX, MSGL_V, " Requirements: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'s','w','r'): demux_info_add(demuxer, "encoder", &text[2]); mp_msg(MSGT_DEMUX, MSGL_V, " Software: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'d','a','y'): mp_msg(MSGT_DEMUX, MSGL_V, " Creation timestamp: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'f','m','t'): mp_msg(MSGT_DEMUX, MSGL_V, " Format: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'p','r','d'): mp_msg(MSGT_DEMUX, MSGL_V, " Producer: %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'p','r','f'): mp_msg(MSGT_DEMUX, MSGL_V, " Performer(s): %s\n", &text[2]); break; case MOV_FOURCC(0xa9,'s','r','c'): mp_msg(MSGT_DEMUX, MSGL_V, " Source providers: %s\n", &text[2]); break; } udta_size -= 4+text_len; break; } /* some other shits: WLOC - window location, LOOP - looping style, SelO - play only selected frames AllF - play all frames */ case MOV_FOURCC('W','L','O','C'): case MOV_FOURCC('L','O','O','P'): case MOV_FOURCC('S','e','l','O'): case MOV_FOURCC('A','l','l','F'): default: { if( udta_len>udta_size) udta_len=udta_size; { char dump[udta_len-4]; stream_read(demuxer->stream, (char *)&dump, udta_len-4-4); udta_size -= udta_len; } } } } break; } /* eof udta */ default: id = be2me_32(id); mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",&id,(int)len); } /* endof switch */ } /* endof else */ pos+=len+8; if(pos>=endpos) break; if(!stream_seek(demuxer->stream,pos)) break; }}int mov_read_header(demuxer_t* demuxer){ mov_priv_t* priv=demuxer->priv; int t_no; int best_a_id=-1, best_a_len=0; int best_v_id=-1, best_v_len=0; mp_msg(MSGT_DEMUX, MSGL_DBG3, "mov_read_header!\n"); // Parse header: stream_reset(demuxer->stream); if(!stream_seek(demuxer->stream,priv->moov_start)) { mp_msg(MSGT_DEMUX,MSGL_ERR,"MOV: Cannot seek to the beginning of the Movie header (0x%x)\n", priv->moov_start); return 0; } lschunks(demuxer, 0, priv->moov_end, NULL); // just in case we have hit eof while parsing... demuxer->stream->eof = 0;// mp_msg(MSGT_DEMUX, MSGL_INFO, "--------------\n"); // find the best (longest) streams: for(t_no=0;t_no<priv->track_db;t_no++){ mov_track_t* trak=priv->tracks[t_no]; int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size; if(demuxer->a_streams[t_no]){ // need audio if(len>best_a_len){ best_a_len=len; best_a_id=t_no; } } if(demuxer->v_streams[t_no]){ // need video if(len>best_v_len){ best_v_len=len; best_v_id=t_no; } } } mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: longest streams: A: #%d (%d samples) V: #%d (%d samples)\n", best_a_id,best_a_len,best_v_id,best_v_len); if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id; if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id; // setup sh pointers: if(demuxer->audio->id>=0){ sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id]; if(sh){ demuxer->audio->sh=sh; sh->ds=demuxer->audio; } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected audio stream (%d) does not exists\n",demuxer->audio->id); demuxer->audio->id=-2; } } if(demuxer->video->id>=0){ sh_video_t* sh=demuxer->v_streams[demuxer->video->id]; if(sh){ demuxer->video->sh=sh; sh->ds=demuxer->video; } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected video stream (%d) does not exists\n",demuxer->video->id); demuxer->video->id=-2; } }#if 1 if(verbose>2){ for(t_no=0;t_no<priv->track_db;t_no++){ mov_track_t* trak=priv->tracks[t_no]; if(trak->type==MOV_TRAK_GENERIC){ int i; int fd; char name[20]; mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size); for (i=0; i<trak->samples_size; i++) { int len=trak->samples[i].size; char buf[len]; stream_seek(demuxer->stream, trak->samples[i].pos); snprintf(name, 20, "t%02d-s%03d.%s", t_no,i, (trak->media_handler==MOV_FOURCC('f','l','s','h')) ? "swf":"dump"); fd = open(name, O_CREAT|O_WRONLY);// { int j;// for(j=0;j<trak->stdata_len-3; j++)// printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b'));// } if( //trak->media_handler==MOV_FOURCC('s','p','r','t') && trak->stdata_len>=16 && char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b') ){ int newlen=stream_read_dword(demuxer->stream);#ifdef HAVE_ZLIB // unzip: z_stream zstrm; int zret; char buf2[newlen]; len-=4; stream_read(demuxer->stream, buf, len); zstrm.zalloc = (alloc_func)0; zstrm.zfree = (free_func)0; zstrm.opaque = (voidpf)0; zstrm.next_in = buf; zstrm.avail_in = len; zstrm.next_out = buf2; zstrm.avail_out = newlen; zret = inflateInit(&zstrm); zret = inflate(&zstrm, Z_NO_FLUSH); if(newlen != zstrm.total_out) mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! unzipped frame size differs hdr: %d zlib: %d\n",newlen,zstrm.total_out); write(fd, buf2, newlen); } else {#else len-=4; printf("******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen); } {#endif stream_read(demuxer->stream, buf, len); write(fd, buf, len); } close(fd); } } } } demuxer->stream->eof = 0;#endif return 1;}/** * \brief return the mov track that belongs to a demuxer stream * \param ds the demuxer stream, may be NULL * \return the mov track info structure belonging to the stream, * NULL if not found */static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) { if (ds && (ds->id >= 0) && (ds->id < priv->track_db)) return priv->tracks[ds->id]; return NULL;}// return value:// 0 = EOF or no stream found// 1 = successfully read a packetint demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ mov_priv_t* priv=demuxer->priv; mov_track_t* trak=NULL; float pts; int x; off_t pos; trak = stream_track(priv, ds); if (!trak) return 0;if(trak->samplesize){ // read chunk: if(trak->pos>=trak->chunks_size) return 0; // EOF stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; if(trak->samplesize!=1) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "WARNING! Samplesize(%d) != 1\n", trak->samplesize); x=trak->chunks[trak->pos].size*trak->samplesize; } else x=trak->chunks[trak->pos].size;// printf("X = %d\n", x); /* the following stuff is audio related */ if (trak->type == MOV_TRAK_AUDIO){ if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ // stsd version 1 - we have audio compression ratio info: x/=char2int(trak->stdata,28); // samples/packet// x*=char2int(trak->stdata,32); // bytes/packet x*=char2int(trak->stdata,36); // bytes/frame } else { if(ds->ss_div && ds->ss_mul){ // workaround for buggy files like 7up-high-traffic-areas.mov, // with missing stsd v1 header containing compression rate x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix ! HACK ! } else { x*=trak->nchannels; x*=trak->samplebytes; } } mp_msg(MSGT_DEMUX, MSGL_DBG2, "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts); } /* MOV_TRAK_AUDIO */ pos=trak->chunks[trak->pos].pos;} else { int frame=trak->pos; // editlist support: if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){ // find the right editlist entry: if(frame<trak->editlist[trak->editlist_pos].start_frame) trak->editlist_pos=0; while(trak->editlist_pos<trak->editlist_size-1 && frame>=trak->editlist[trak->editlist_pos+1].start_frame) ++trak->editlist_pos; if(frame>=trak->editlist[trak->editlist_pos].start_frame+ trak->editlist[trak->editlist_pos].frames) return 0; // EOF // calc real frame index: frame-=trak->editlist[trak->editlist_pos].start_frame; frame+=trak->editlist[trak->editlist_pos].start_sample; // calc pts: pts=(float)(trak->samples[frame].pts+ trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale; } else { if(frame>=trak->samples_size) return 0; // EOF pts=(float)trak->samples[frame].pts/(float)trak->timescale; } // read sample: stream_seek(demuxer->stream,trak->samples[frame].pos); x=trak->samples[frame].size; pos=trak->samples[frame].pos;}if(trak->pos==0 && trak->stream_header_len>0){ // we have to append the stream header... demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len); memcpy(dp->buffer,trak->stream_header,trak->stream_header_len); stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x); free(trak->stream_header); trak->stream_header = NULL; trak->stream_header_len = 0; dp->pts=pts; dp->flags=0; dp->pos=pos; // FIXME? ds_add_packet(ds,dp);} else ds_read_packet(ds,demuxer->stream,x,pts,pos,0); ++trak->pos; return 1; }static float mov_seek_track(mov_track_t* trak,float pts,int flags){// printf("MOV track seek called %5.3f \n",pts); if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale;if(trak->samplesize){ int sample=pts/trak->duration;// printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative trak->pos=0; while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;} else { unsigned int ipts; if(!(flags&1)) pts+=trak->samples[trak->pos].pts; if(pts<0) pts=0; ipts=pts; //printf("MOV track seek - sample: %d \n",ipts); for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){ if(trak->samples[trak->pos].pts>=ipts) break; // found it! } if(trak->keyframes_size){ // find nearest keyframe int i; for(i=0;i<trak->keyframes_size;i++){ if(trak->keyframes[i]>=trak->pos) break; } if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1])) --i; trak->pos=trak->keyframes[i];// printf("nearest keyframe: %d \n",trak->pos); } pts=(float)trak->samples[trak-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -