demux_real_1.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,824 行 · 第 1/5 页
C
1,824 行
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; priv->audio_timestamp[priv->sub_packet_cnt] = (priv->a_pts==timestamp) ? (correct_pts ? MP_NOPTS_VALUE : 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;// 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); 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[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){ 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! dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length+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; 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; 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): 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){ 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); } // 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((unsigned)stream_id<MAX_STREAMS){ 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; priv->audio_buf = calloc(priv->sub_packet_h[demuxer->audio->id], priv->audiopk_size[demuxer->audio->id]); priv->audio_timestamp = calloc(priv->sub_packet_h[demuxer->audio->id], sizeof(double)); 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; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?