demux_real.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,820 行 · 第 1/5 页
C
1,820 行
(priv->intl_id[stream_id] == mmioFOURCC('g', 'e', 'n', 'r')) || (priv->intl_id[stream_id] == mmioFOURCC('s', 'i', 'p', 'r'))) { sps = priv->sub_packet_size[stream_id]; sph = priv->sub_packet_h[stream_id]; cfs = priv->coded_framesize[stream_id]; w = priv->audiopk_size[stream_id]; spc = priv->sub_packet_cnt; switch (priv->intl_id[stream_id]) { case mmioFOURCC('I', 'n', 't', '4'): if (len < cfs * sph/2) goto discard; for (x = 0; x < sph / 2; x++) stream_read(demuxer->stream, priv->audio_buf + x * 2 * w + spc * cfs, cfs); break; case mmioFOURCC('g', 'e', 'n', 'r'): if (len < w) goto discard; for (x = 0; x < w / sps; x++) stream_read(demuxer->stream, priv->audio_buf + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1)), sps); break; case mmioFOURCC('s', 'i', 'p', 'r'): if (len < w) goto discard; stream_read(demuxer->stream, priv->audio_buf + spc * w, w); if (spc == sph - 1) { int n; int bs = sph * w * 2 / 96; // nibbles per subpacket // Perform reordering for(n=0; n < 38; n++) { int j; int i = bs * sipr_swaps[n][0]; int o = bs * sipr_swaps[n][1]; // swap nibbles of block 'i' with 'o' TODO: optimize for(j = 0;j < bs; j++) { int x = (i & 1) ? (priv->audio_buf[i >> 1] >> 4) : (priv->audio_buf[i >> 1] & 0x0F); int y = (o & 1) ? (priv->audio_buf[o >> 1] >> 4) : (priv->audio_buf[o >> 1] & 0x0F); if(o & 1) priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0x0F) | (x << 4); else priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0xF0) | x; if(i & 1) priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0x0F) | (y << 4); else priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0xF0) | y; ++i; ++o; } } } break; } priv->audio_need_keyframe = 0; //(user_correct_pts > 0 ? MP_NOPTS_VALUE : 0) priv->audio_timestamp[priv->sub_packet_cnt] = (priv->a_pts==timestamp) ? 0 : (timestamp/1000.0); priv->a_pts = timestamp; if (priv->sub_packet_cnt == 0) priv->audio_filepos = demuxer->filepos; if (++(priv->sub_packet_cnt) < sph) audioreorder_getnextpk = 1; else { int apk_usize = ((WAVEFORMATEX*)((sh_audio_t*)ds->sh)->wf)->nBlockAlign; audioreorder_getnextpk = 0; priv->sub_packet_cnt = 0; // Release all the audio packets for (x = 0; x < sph*w/apk_usize; x++) { dp = new_demux_packet(apk_usize); memcpy(dp->buffer, priv->audio_buf + x * apk_usize, apk_usize); /* Put timestamp only on packets that correspond to original audio packets in file */ if (x * apk_usize % w == 0) dp->pts = priv->audio_timestamp[x * apk_usize / w]; dp->pos = priv->audio_filepos; // all equal dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe ds_add_packet(ds, dp); } } } else { // No interleaving dp = new_demux_packet(len); stream_read(demuxer->stream, dp->buffer, len);#ifdef CRACK_MATRIX mp_msg(MSGT_DEMUX, MSGL_V,"*** audio block len=%d\n",len); { // HACK - used for reverse engineering the descrambling matrix FILE* f=fopen("test.rm","r+"); fseek(f,spos,SEEK_SET); ++cnt;// for(i=0;i<len;i++) dp->buffer[i]=i/0x12;// for(i=0;i<len;i++) dp->buffer[i]=i;// for(i=0;i<len;i++) dp->buffer[i]=cnt;// for(i=0;i<len;i++) dp->buffer[i]=cnt<<4; for(i=0;i<len;i++) dp->buffer[i]=(i==cnt2) ? (cnt+16*(8+cnt)) : 0; if(cnt==6){ cnt=0; ++cnt2; } fwrite(dp->buffer, len, 1, f); fclose(f); if(cnt2>0x150) *((int*)NULL)=1; // sig11 :) }#endif#if 0 if( ((sh_audio_t *)ds->sh)->format == 0x2000) { // if DNET, swap bytes, as DNET is byte-swapped AC3: char *ptr = dp->buffer; int i; for (i = 0; i < len; i += 2) { const char tmp = ptr[0]; ptr[0] = ptr[1]; ptr[1] = tmp; ptr += 2; } }#endif if (priv->audio_need_keyframe == 1) { priv->audio_need_keyframe = 0; } else if(priv->a_pts != timestamp) dp->pts = timestamp/1000.0; priv->a_pts=timestamp; dp->pos = demuxer->filepos; dp->flags = (flags & 0x2) ? 0x10 : 0; ds_add_packet(ds, dp); } // codec_id check, codec default case }// we will not use audio index if we use -idx and have a video if(!demuxer->video->sh && index_mode == 2 && (unsigned)demuxer->audio->id < MAX_STREAMS) while (priv->current_apacket + 1 < priv->index_table_size[demuxer->audio->id] && timestamp > priv->index_table[demuxer->audio->id][priv->current_apacket].timestamp) priv->current_apacket += 1; if(priv->is_multirate) while (priv->a_idx_ptr + 1 < priv->index_table_size[demuxer->audio->id] && timestamp > priv->index_table[demuxer->audio->id][priv->a_idx_ptr + 1].timestamp) { priv->a_idx_ptr++; priv->audio_curpos = stream_tell(demuxer->stream); priv->stream_switch = 1; } // If we're reordering audio packets and we need more data get it if (audioreorder_getnextpk) continue; return 1; } if(demuxer->video->id==stream_id){got_video: ds=demuxer->video; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is video (id: %d)\n", stream_id); // parse video chunk: { // we need a more complicated, 2nd level demuxing, as the video // frames are stored fragmented in the video chunks :( sh_video_t *sh_video = ds->sh; demux_packet_t *dp; unsigned vpkg_header, vpkg_length, vpkg_offset; int vpkg_seqnum=-1; int vpkg_subseq=0; while(len>2){ dp_hdr_t* dp_hdr; unsigned char* dp_data; uint32_t* extra; // unsigned char *extra;// printf("xxx len=%d \n",len); // read packet header // bit 7: 1=last block in block chain // bit 6: 1=short header (only one block?) vpkg_header=stream_read_char(demuxer->stream); --len; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "hdr: %02X (len=%d) ",vpkg_header,len); if (0x40==(vpkg_header&0xc0)) { // seems to be a very short header // 2 bytes, purpose of the second byte yet unknown int bummer; bummer=stream_read_char(demuxer->stream); --len; mp_dbg(MSGT_DEMUX,MSGL_DBG2, "%02X",bummer); vpkg_offset=0; vpkg_length=len; } else { if (0==(vpkg_header&0x40)) { // 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|=(uint16_t)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|=(uint16_t)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); //extra=(unsigned char*)(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){ priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; dp->pts= real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); priv->video_after_seek = 0; } else if (dp_hdr->len >= 3) dp->pts = 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+FF_INPUT_BUFFER_PADDING_SIZE); memset(dp->buffer + dp->len, 0, FF_INPUT_BUFFER_PADDING_SIZE); // 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=(unsigned char *)(dp->buffer+dp_hdr->chunktab); } extra[2*dp_hdr->chunks+0]=1; extra[2*dp_hdr->chunks+1]=dp_hdr->len; //extra[2*dp_hdr->chunks + 0]=1; //extra[2*dp_hdr->chunks + 1]=0; //extra[2*dp_hdr->chunks + 2]=0; //extra[2*dp_hdr->chunks + 3]=0; //extra[2*dp_hdr->chunks + 4]=dp_hdr->len & 0x0ff; //extra[2*dp_hdr->chunks + 5]=(dp_hdr->len >> 8) & 0x0ff; //extra[2*dp_hdr->chunks + 6]=(dp_hdr->len >> 16) & 0x0ff; //extra[2*dp_hdr->chunks + 7]=(dp_hdr->len >> 24) & 0x0ff; 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){ priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; dp->pts= real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); priv->video_after_seek = 0; } else if (dp_hdr->len >= 3) dp->pts = 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! int vpkg_length_align = ((vpkg_length + 3) & (~3)); //dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length+8*(1+2*(vpkg_header&0x3F))); dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length_align+8*(1+2*((vpkg_header)&0x3F))); // the timestamp seems to be in milliseconds 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_align; dp_data=dp->buffer+sizeof(dp_hdr_t); //extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab); extra=(unsigned char*)(dp->buffer+dp_hdr->chunktab); extra[0]=1; extra[1]=0; // offset of the first chunk// extra[0] = 1;// extra[1] = 0;// extra[2] = 0;// extra[3] = 0;// extra[4] = 0;// extra[5] = 0;// extra[6] = 0;// extra[7] = 0; if(0x00==(vpkg_header&0xc0)){ // first fragment: //F("vpkg_length = %d len = %d\n",vpkg_length,len); if(vpkg_length >= len) { dp_hdr->len=len; stream_read(demuxer->stream, dp_data, len); } else { dp_hdr->len=vpkg_length; stream_read(demuxer->stream, dp_data,vpkg_length ); seterrorseek(); } ds->asf_packet=dp; len=0; if(priv->video_after_seek){ priv->kf_base = 0; priv->kf_pts = dp_hdr->timestamp; dp->pts= real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format); priv->video_after_seek = 0; } break; } // whole packet (not fragmented):
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?