📄 demux_real.c
字号:
// sub-seqnum (bits 0-6: number of fragment. bit 7: ???) vpkg_subseq=stream_read_char(demuxer->stream); --len; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "subseq: %02X ",vpkg_subseq); vpkg_subseq&=0x7f; } // size of the complete packet // bit 14 is always one (same applies to the offset) vpkg_length=stream_read_word(demuxer->stream); len-=2; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "l: %02X %02X ",vpkg_length>>8,vpkg_length&0xff); if (!(vpkg_length&0xC000)) { vpkg_length<<=16; vpkg_length|=stream_read_word(demuxer->stream); mp_dbg(MSGT_DEMUX,MSGL_DBG2, "l+: %02X %02X ",(vpkg_length>>8)&0xff,vpkg_length&0xff); len-=2; } else vpkg_length&=0x3fff; // offset of the following data inside the complete packet // Note: if (hdr&0xC0)==0x80 then offset is relative to the // _end_ of the packet, so it's equal to fragment size!!! vpkg_offset=stream_read_word(demuxer->stream); len-=2; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "o: %02X %02X ",vpkg_offset>>8,vpkg_offset&0xff); if (!(vpkg_offset&0xC000)) { vpkg_offset<<=16; vpkg_offset|=stream_read_word(demuxer->stream); mp_dbg(MSGT_DEMUX,MSGL_DBG2, "o+: %02X %02X ",(vpkg_offset>>8)&0xff,vpkg_offset&0xff); len-=2; } else vpkg_offset&=0x3fff; vpkg_seqnum=stream_read_char(demuxer->stream); --len; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "seq: %02X ",vpkg_seqnum); } mp_dbg(MSGT_DEMUX,MSGL_DBG2, "\n"); mp_dbg(MSGT_DEMUX,MSGL_DBG2, "blklen=%d\n", len); mp_msg(MSGT_DEMUX,MSGL_DBG2, "block: hdr=0x%0x, len=%d, offset=%d, seqnum=%d\n", vpkg_header, vpkg_length, vpkg_offset, vpkg_seqnum); if(ds->asf_packet){ dp=ds->asf_packet; dp_hdr=(dp_hdr_t*)dp->buffer; dp_data=dp->buffer+sizeof(dp_hdr_t); extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab); mp_dbg(MSGT_DEMUX,MSGL_DBG2, "we have an incomplete packet (oldseq=%d new=%d)\n",ds->asf_seq,vpkg_seqnum); // we have an incomplete packet: if(ds->asf_seq!=vpkg_seqnum){ // this fragment is for new packet, close the old one mp_msg(MSGT_DEMUX,MSGL_DBG2, "closing probably incomplete packet, len: %d \n",dp->len); if(priv->video_after_seek){ dp->pts=timestamp; priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; priv->video_after_seek = 0; } else dp->pts=(dp_hdr->len<3)?0: real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); ds_add_packet(ds,dp); ds->asf_packet=NULL; } else { // append data to it! ++dp_hdr->chunks; mp_msg(MSGT_DEMUX,MSGL_DBG2,"[chunks=%d subseq=%d]\n",dp_hdr->chunks,vpkg_subseq); if(dp_hdr->chunktab+8*(1+dp_hdr->chunks)>dp->len){ // increase buffer size, this should not happen! mp_msg(MSGT_DEMUX,MSGL_WARN, "chunktab buffer too small!!!!!\n"); dp->len=dp_hdr->chunktab+8*(4+dp_hdr->chunks); dp->buffer=realloc(dp->buffer,dp->len); // re-calc pointers: dp_hdr=(dp_hdr_t*)dp->buffer; dp_data=dp->buffer+sizeof(dp_hdr_t); extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab); } extra[2*dp_hdr->chunks+0]=1; extra[2*dp_hdr->chunks+1]=dp_hdr->len; if(0x80==(vpkg_header&0xc0)){ // last fragment! if(dp_hdr->len!=vpkg_length-vpkg_offset) mp_msg(MSGT_DEMUX,MSGL_V,"warning! assembled.len=%d frag.len=%d total.len=%d \n",dp->len,vpkg_offset,vpkg_length-vpkg_offset); stream_read(demuxer->stream, dp_data+dp_hdr->len, vpkg_offset); if((dp_data[dp_hdr->len]&0x20) && (sh_video->format==0x30335652)) --dp_hdr->chunks; else dp_hdr->len+=vpkg_offset; len-=vpkg_offset; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "fragment (%d bytes) appended, %d bytes left\n",vpkg_offset,len); // we know that this is the last fragment -> we can close the packet! if(priv->video_after_seek){ dp->pts=timestamp; priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; priv->video_after_seek = 0; } else dp->pts=(dp_hdr->len<3)?0: real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); ds_add_packet(ds,dp); ds->asf_packet=NULL; // continue parsing continue; } // non-last fragment: if(dp_hdr->len!=vpkg_offset) mp_msg(MSGT_DEMUX,MSGL_V,"warning! assembled.len=%d offset=%d frag.len=%d total.len=%d \n",dp->len,vpkg_offset,len,vpkg_length); stream_read(demuxer->stream, dp_data+dp_hdr->len, len); if((dp_data[dp_hdr->len]&0x20) && (sh_video->format==0x30335652)) --dp_hdr->chunks; else dp_hdr->len+=len; len=0; break; // no more fragments in this chunk! } } // create new packet! dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length+8*(1+2*(vpkg_header&0x3F))); // the timestamp seems to be in milliseconds dp->pts = 0; // timestamp/1000.0f; //timestamp=0; dp->pos = demuxer->filepos; dp->flags = (flags & 0x2) ? 0x10 : 0; ds->asf_seq = vpkg_seqnum; dp_hdr=(dp_hdr_t*)dp->buffer; dp_hdr->chunks=0; dp_hdr->timestamp=timestamp; dp_hdr->chunktab=sizeof(dp_hdr_t)+vpkg_length; dp_data=dp->buffer+sizeof(dp_hdr_t); extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab); extra[0]=1; extra[1]=0; // offset of the first chunk if(0x00==(vpkg_header&0xc0)){ // first fragment: dp_hdr->len=len; stream_read(demuxer->stream, dp_data, len); ds->asf_packet=dp; len=0; break; } // whole packet (not fragmented): if (vpkg_length > len) { mp_msg(MSGT_DEMUX, MSGL_WARN,"\n******** WARNING: vpkg_length=%i > len=%i ********\n", vpkg_length, len); /* * To keep the video stream rolling, we need to break * here. We shouldn't touch len to make sure rest of the * broken packet is skipped. */ break; } dp_hdr->len=vpkg_length; len-=vpkg_length; stream_read(demuxer->stream, dp_data, vpkg_length); if(priv->video_after_seek){ dp->pts=timestamp; priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; priv->video_after_seek = 0; } else dp->pts=(dp_hdr->len<3)?0: real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); ds_add_packet(ds,dp); } // while(len>0) if(len){ mp_msg(MSGT_DEMUX, MSGL_WARN,"\n******** !!!!!!!! BUG!! len=%d !!!!!!!!!!! ********\n",len); if(len>0) stream_skip(demuxer->stream, len); } } if ((unsigned)demuxer->video->id < MAX_STREAMS) while (priv->current_vpacket + 1 < priv->index_table_size[demuxer->video->id] && timestamp > priv->index_table[demuxer->video->id][priv->current_vpacket + 1].timestamp) priv->current_vpacket += 1; if(priv->is_multirate) while (priv->v_idx_ptr + 1 < priv->index_table_size[demuxer->video->id] && timestamp > priv->index_table[demuxer->video->id][priv->v_idx_ptr + 1].timestamp) { priv->v_idx_ptr++; priv->video_curpos = stream_tell(demuxer->stream); priv->stream_switch = 1; } return 1; }if(stream_id<256){ if(demuxer->audio->id==-1 && demuxer->a_streams[stream_id]){ sh_audio_t *sh = demuxer->a_streams[stream_id]; demuxer->audio->id=stream_id; sh->ds=demuxer->audio; demuxer->audio->sh=sh; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM audio ID = %d\n",stream_id); goto got_audio; } if(demuxer->video->id==-1 && demuxer->v_streams[stream_id]){ sh_video_t *sh = demuxer->v_streams[stream_id]; demuxer->video->id=stream_id; sh->ds=demuxer->video; demuxer->video->sh=sh; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM video ID = %d\n",stream_id); goto got_video; }} mp_msg(MSGT_DEMUX,MSGL_DBG2, "unknown stream id (%d)\n", stream_id);discard: stream_skip(demuxer->stream, len); }// goto loop;}extern void print_wave_header(WAVEFORMATEX *h);void demux_open_real(demuxer_t* demuxer){ real_priv_t* priv = demuxer->priv; int num_of_headers; int a_streams=0; int v_streams=0; int i; int header_size; header_size = stream_read_dword(demuxer->stream); /* header size */ mp_msg(MSGT_DEMUX,MSGL_V, "real: Header size: %d\n", header_size); i = stream_read_word(demuxer->stream); /* version */ mp_msg(MSGT_DEMUX,MSGL_V, "real: Header object version: %d\n", i); if (header_size == 0x10) i = stream_read_word(demuxer->stream); else /* we should test header_size here too. */ i = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V, "real: File version: %d\n", i); num_of_headers = stream_read_dword(demuxer->stream);// stream_skip(demuxer->stream, 4); /* number of headers */ /* parse chunks */ for (i = 1; i <= num_of_headers; i++)// for (i = 1; ; i++) { int chunk_id, chunk_pos, chunk_size; chunk_pos = stream_tell(demuxer->stream); chunk_id = stream_read_dword_le(demuxer->stream); chunk_size = stream_read_dword(demuxer->stream); stream_skip(demuxer->stream, 2); /* version */ mp_msg(MSGT_DEMUX,MSGL_V, "Chunk: %.4s (%x) (size: 0x%x, offset: 0x%x)\n", (char *)&chunk_id, chunk_id, chunk_size, chunk_pos); if (chunk_size < 10){ mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_real: invalid chunksize! (%d)\n",chunk_size); break; //return; } switch(chunk_id) { case MKTAG('P', 'R', 'O', 'P'): /* Properties header */ stream_skip(demuxer->stream, 4); /* max bitrate */ stream_skip(demuxer->stream, 4); /* avg bitrate */ stream_skip(demuxer->stream, 4); /* max packet size */ stream_skip(demuxer->stream, 4); /* avg packet size */ stream_skip(demuxer->stream, 4); /* nb packets */ priv->duration = stream_read_dword(demuxer->stream)/1000; /* duration */ //stream_skip(demuxer->stream, 4); /* duration */ stream_skip(demuxer->stream, 4); /* preroll */ priv->index_chunk_offset = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"First index chunk offset: 0x%x\n", priv->index_chunk_offset); priv->data_chunk_offset = stream_read_dword(demuxer->stream)+10; mp_msg(MSGT_DEMUX,MSGL_V,"First data chunk offset: 0x%x\n", priv->data_chunk_offset); stream_skip(demuxer->stream, 2); /* nb streams */#if 0 stream_skip(demuxer->stream, 2); /* flags */#else { int flags = stream_read_word(demuxer->stream); if (flags) { mp_msg(MSGT_DEMUX,MSGL_V,"Flags (%x): ", flags); if (flags & 0x1) mp_msg(MSGT_DEMUX,MSGL_V,"[save allowed] "); if (flags & 0x2) mp_msg(MSGT_DEMUX,MSGL_V,"[perfect play (more buffers)] "); if (flags & 0x4) mp_msg(MSGT_DEMUX,MSGL_V,"[live broadcast] "); mp_msg(MSGT_DEMUX,MSGL_V,"\n"); } }#endif break; case MKTAG('C', 'O', 'N', 'T'): { /* Content description header */ char *buf; int len; len = stream_read_word(demuxer->stream); if (len > 0) { buf = malloc(len+1); stream_read(demuxer->stream, buf, len); buf[len] = 0; demux_info_add(demuxer, "name", buf); free(buf); } len = stream_read_word(demuxer->stream); if (len > 0) { buf = malloc(len+1); stream_read(demuxer->stream, buf, len); buf[len] = 0; demux_info_add(demuxer, "author", buf); free(buf); } len = stream_read_word(demuxer->stream); if (len > 0) { buf = malloc(len+1); stream_read(demuxer->stream, buf, len); buf[len] = 0; demux_info_add(demuxer, "copyright", buf); free(buf); } len = stream_read_word(demuxer->stream); if (len > 0) { buf = malloc(len+1); stream_read(demuxer->stream, buf, len); buf[len] = 0; demux_info_add(demuxer, "comment", buf); free(buf); } break; } case MKTAG('M', 'D', 'P', 'R'): { /* Media properties header */ int stream_id; int bitrate; int codec_data_size; int codec_pos; int tmp; int len; char *descr, *mimet; stream_id = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"Found new stream (id: %d)\n", stream_id); stream_skip(demuxer->stream, 4); /* max bitrate */ bitrate = stream_read_dword(demuxer->stream); /* avg bitrate */ stream_skip(demuxer->stream, 4); /* max packet size */ stream_skip(demuxer->stream, 4); /* avg packet size */ stream_skip(demuxer->stream, 4); /* start time */ stream_skip(demuxer->stream, 4); /* preroll */ stream_skip(demuxer->stream, 4); /* duration */ // skip_str(1, demuxer); /* stream description (name) */ if ((len = stream_read_char(demuxer->stream)) > 0) { descr = malloc(len+1); stream_read(demuxer->stream, descr, len); descr[len] = 0; printf("Stream description: %s\n", descr); free(descr); }// skip_str(1, demuxer); /* mimetype */ if ((len = stream_read_char(demuxer->stream)) > 0) { mimet = malloc(len+1); stream_read(demuxer->stream, mimet, len); mimet[len] = 0; printf("Stream mimetype: %s\n", mimet); } /* Type specific header */ codec_data_size = stream_read_dword(demuxer->stream); codec_pos = stream_tell(demuxer->stream);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -