📄 demux_mpg.c
字号:
c=stream_read_char(demux->stream); //pes_extension2 payload === substream id hdrlen--; if(c<0x55 || c>0x5F) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown vc1 substream_id: 0x%x \n", c); return -1;} pes_ext2_subid=c; } if(hdrlen>0) stream_skip(demux->stream,hdrlen); // skip header and stuffing bytes if(id==0x1FD && pes_ext2_subid!=-1) { //==== EVO VC1 STREAMS ===// if(!demux->v_streams[pes_ext2_subid]) new_sh_video(demux,pes_ext2_subid); if(demux->video->id==-1) demux->video->id=pes_ext2_subid; if(demux->video->id==pes_ext2_subid){ ds=demux->video; if(!ds->sh) ds->sh=demux->v_streams[pes_ext2_subid]; if(priv && ds->sh) { sh_video_t *sh = (sh_video_t *)ds->sh; sh->format = mmioFOURCC('W', 'V', 'C', '1'); } } } //============== DVD Audio sub-stream ====================== if(id==0x1BD){ int aid, rawa52 = 0; off_t tmppos; unsigned int tmp; tmppos = stream_tell(demux->stream); tmp = stream_read_word(demux->stream); stream_seek(demux->stream, tmppos); /// vdr stores A52 without the 4 header bytes, so we have to check this condition first if(tmp == 0x0B77) { aid = 128; rawa52 = 1; } else { aid=stream_read_char(demux->stream);--len; if(len<3) return -1; // invalid audio packet } // AID: // 0x20..0x3F subtitle // 0x80..0x87 and 0xC0..0xCF AC3 audio // 0x88..0x8F and 0x98..0x9F DTS audio // 0xA0..0xBF PCM audio if((aid & 0xE0) == 0x20){ // subtitle: aid&=0x1F; if(!demux->s_streams[aid]){ sh_sub_t *sh = new_sh_sub(demux, aid); if (sh) sh->type = 'v'; mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid); } if(demux->sub->id > -1) demux->sub->id &= 0x1F; if(!dvdsub_lang && demux->sub->id == -1) demux->sub->id = aid; if(demux->sub->id==aid){ ds=demux->sub; } } else if((aid >= 0x80 && aid <= 0x8F) || (aid >= 0x98 && aid <= 0xAF) || (aid >= 0xC0 && aid <= 0xCF)) {// aid=128+(aid&0x7F); // aid=0x80..0xBF new_audio_stream(demux, aid); if(demux->audio->id==aid){ int type; ds=demux->audio; if(!ds->sh) ds->sh=demux->a_streams[aid]; // READ Packet: Skip additional audio header data: if(!rawa52) { c=stream_read_char(demux->stream);//num of frames type=stream_read_char(demux->stream);//startpos hi type=(type<<8)|stream_read_char(demux->stream);//startpos lo// printf("\r[%02X][%04X]",c,type); len-=3; } if((aid&0xE0)==0xA0 && len>=3){ unsigned char* hdr; // save audio header as codecdata! if(!((sh_audio_t*)(ds->sh))->codecdata_len){ ((sh_audio_t*)(ds->sh))->codecdata=malloc(3); ((sh_audio_t*)(ds->sh))->codecdatatype = 1; ((sh_audio_t*)(ds->sh))->codecdata_len=3; } hdr=((sh_audio_t*)(ds->sh))->codecdata; // read LPCM header: // emphasis[1], mute[1], rvd[1], frame number[5]: hdr[0]=stream_read_char(demux->stream);// printf(" [%01X:%02d]",c>>5,c&31); // quantization[2],freq[2],rvd[1],channels[3] hdr[1]=stream_read_char(demux->stream);// printf("[%01X:%01X] ",c>>4,c&15); // dynamic range control (0x80=off): hdr[2]=stream_read_char(demux->stream);// printf("[%02X] ",c); len-=3; if(len<=0) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n"); }// printf(" \n"); } // if(demux->audio->id==aid) } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid); } //if(id==0x1BD) } else { if(c!=0x0f){ mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c); return -1; // invalid packet !!!!!! } } if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error); mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len);// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size if(len<=0 || len>MAX_PS_PACKETSIZE){ mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len); return -1; // invalid packet !!!!!! } if(id>=0x1C0 && id<=0x1DF){ // mpeg audio int aid=id-0x1C0; new_audio_stream(demux, aid); if(demux->audio->id==aid){ ds=demux->audio; if(!ds->sh) ds->sh=demux->a_streams[aid]; if(priv && ds->sh) { sh_audio_t *sh = (sh_audio_t *)ds->sh; if(priv->es_map[id - 0x1B0]) sh->format = priv->es_map[id - 0x1B0]; mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); } } } else if(id>=0x1E0 && id<=0x1EF){ // mpeg video int aid=id-0x1E0; if(!demux->v_streams[aid]) new_sh_video(demux,aid); if(demux->video->id==-1) demux->video->id=aid; if(demux->video->id==aid){ ds=demux->video; if(!ds->sh) ds->sh=demux->v_streams[aid]; if(priv && ds->sh) { sh_video_t *sh = (sh_video_t *)ds->sh; if(priv->es_map[id - 0x1B0]) { sh->format = priv->es_map[id - 0x1B0]; mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]); } } } } if(ds){ mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos); dp=new_demux_packet(len); if(!dp) { mp_dbg(MSGT_DEMUX,MSGL_ERR,"DEMUX_MPG ERROR: couldn't create demux_packet(%d bytes)\n",len); stream_skip(demux->stream,len); return 0; } l = stream_read(demux->stream,dp->buffer,len); if(l<len) resize_demux_packet(dp, l); len = l; dp->pts=pts/90000.0f; dp->pos=demux->filepos; /* workaround: set dp->stream_pts only when feeding the video stream, or strangely interleaved files (such as SWIII) will show strange alternations in the stream time, wildly going back and forth */ if(ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME,(void *)&stream_pts)!=STREAM_UNSUPPORTED) dp->stream_pts = stream_pts; ds_add_packet(ds,dp); if (demux->priv && set_pts) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len); return 1; } mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id); if(len<=2356) stream_skip(demux->stream,len); return 0;}static int num_elementary_packets100=0;static int num_elementary_packets101=0;static int num_elementary_packets12x=0;static int num_elementary_packets1B6=0;static int num_elementary_packetsPES=0;static int num_h264_slice=0; //combined slicestatic int num_h264_dpa=0; //DPA Slicestatic int num_h264_dpb=0; //DPB Slicestatic int num_h264_dpc=0; //DPC Slicestatic int num_h264_idr=0; //IDR Slicestatic int num_h264_sps=0;static int num_h264_pps=0;static int num_mp3audio_packets=0;static void clear_stats(void){ num_elementary_packets100=0; num_elementary_packets101=0; num_elementary_packets1B6=0; num_elementary_packets12x=0; num_elementary_packetsPES=0; num_h264_slice=0; //combined slice num_h264_dpa=0; //DPA Slice num_h264_dpb=0; //DPB Slice num_h264_dpc=0; //DPC Slice num_h264_idr=0; //IDR Slice num_h264_sps=0; num_h264_pps=0; num_mp3audio_packets=0;}//assumes demuxer->synced < 2static inline void update_stats(int head){ if(head==0x1B6) ++num_elementary_packets1B6; else if(head==0x100) ++num_elementary_packets100; else if(head==0x101) ++num_elementary_packets101; else if(head==0x1BD || (0x1C0<=head && head<=0x1EF)) num_elementary_packetsPES++; else if(head>=0x120 && head<=0x12F) ++num_elementary_packets12x; if(head>=0x100 && head<0x1B0) { if((head&~0x60) == 0x101) ++num_h264_slice; else if((head&~0x60) == 0x102) ++num_h264_dpa; else if((head&~0x60) == 0x103) ++num_h264_dpb; else if((head&~0x60) == 0x104) ++num_h264_dpc; else if((head&~0x60) == 0x105 && head != 0x105) ++num_h264_idr; else if((head&~0x60) == 0x107 && head != 0x107) ++num_h264_sps; else if((head&~0x60) == 0x108 && head != 0x108) ++num_h264_pps; }}static int demux_mpg_probe(demuxer_t *demuxer) { int pes=1; int tmp; off_t tmppos; int file_format = DEMUXER_TYPE_UNKNOWN; tmppos=stream_tell(demuxer->stream); tmp=stream_read_dword(demuxer->stream); if(tmp==0x1E0 || tmp==0x1C0) { tmp=stream_read_word(demuxer->stream); if(tmp>1 && tmp<=2048) pes=0; // demuxer->synced=3; // PES... } stream_seek(demuxer->stream,tmppos); clear_stats(); if(demux_mpg_open(demuxer)) file_format=DEMUXER_TYPE_MPEG_PS; else { mp_msg(MSGT_DEMUX,MSGL_V,"MPEG packet stats: p100: %d p101: %d p1B6: %d p12x: %d sli: %d a: %d b: %d c: %d idr: %d sps: %d pps: %d PES: %d MP3: %d, synced: %d\n", num_elementary_packets100,num_elementary_packets101, num_elementary_packets1B6,num_elementary_packets12x, num_h264_slice, num_h264_dpa, num_h264_dpb, num_h264_dpc=0, num_h264_idr, num_h264_sps=0, num_h264_pps, num_elementary_packetsPES,num_mp3audio_packets, demuxer->synced); //MPEG packet stats: p100: 458 p101: 458 PES: 0 MP3: 1103 (.m2v) if(num_mp3audio_packets>50 && num_mp3audio_packets>2*num_elementary_packets100 && abs(num_elementary_packets100-num_elementary_packets101)>2) return file_format; // some hack to get meaningfull error messages to our unhappy users: if(num_elementary_packets100>=2 && num_elementary_packets101>=2 && abs(num_elementary_packets101+8-num_elementary_packets100)<16) { if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4) { return file_format; } file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :) } else // fuzzy mpeg4-es detection. do NOT enable without heavy testing of mpeg formats detection! if(num_elementary_packets1B6>3 && num_elementary_packets12x>=1 && num_elementary_packetsPES==0 && num_elementary_packets100<=num_elementary_packets12x && demuxer->synced<2) { file_format=DEMUXER_TYPE_MPEG4_ES; } else // fuzzy h264-es detection. do NOT enable without heavy testing of mpeg formats detection! if((num_h264_slice>3 || (num_h264_dpa>3 && num_h264_dpb>3 && num_h264_dpc>3)) && /* FIXME num_h264_sps>=1 && */ num_h264_pps>=1 && num_h264_idr>=1 && num_elementary_packets1B6==0 && num_elementary_packetsPES==0 && demuxer->synced<2) { file_format=DEMUXER_TYPE_H264_ES; } else { if(demuxer->synced==2) mp_msg(MSGT_DEMUXER,MSGL_ERR,"MPEG: " MSGTR_MissingVideoStreamBug); else mp_msg(MSGT_DEMUXER,MSGL_V,MSGTR_NotSystemStream); } } //FIXME this shouldn't be necessary stream_seek(demuxer->stream,tmppos); return file_format;}static int demux_mpg_es_fill_buffer(demuxer_t *demux, demux_stream_t *ds){ // Elementary video stream if(demux->stream->eof) return 0; demux->filepos=stream_tell(demux->stream); ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0); return 1;}/** * \brief discard until 0x100 header and return a filled buffer * \param b buffer-end pointer * \param pos current pos in stream, negative since b points to end of buffer * \param s stream to read from * \return new position, differs from original pos when eof hit and thus * b was modified to point to the new end of buffer */static int find_end(unsigned char **b, int pos, stream_t *s) { register int state = 0xffffffff; unsigned char *buf = *b; int start = pos; int read, unused; // search already read part while (state != 0x100 && pos) { state = state << 8 | buf[pos++]; } // continue search in stream while (state != 0x100) { register int c = stream_read_char(s); if (c < 0) break; state = state << 8 | c; } // modify previous header (from 0x1bc or 0x1bf to 0x100) buf[start++] = 0; // copy remaining buffer part to current pos memmove(&buf[start], &buf[pos], -pos); unused = start + -pos; // -unused bytes in buffer read = stream_read(s, &buf[unused], -unused); unused += read; // fix buffer so it ends at pos == 0 (eof case) *b = &buf[unused]; start -= unused; return start;}/** * This format usually uses an insane bitrate, which makes this function * performance-critical! * Be sure to benchmark any changes with different compiler versions. */static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) { demux_packet_t *pack; int len; demux->filepos = stream_tell(demux->stream); pack = new_demux_packet(STREAM_BUFFER_SIZE); len = stream_read(demux->stream, pack->buffer, STREAM_BUFFER_SIZE); if (len <= 0) { free_demux_packet(pack); return 0; } { register uint32_t state = (uint32_t)demux->priv; register int pos = -len; unsigned char *buf = &pack->buffer[len]; do { state = state << 8 | buf[pos]; if (unlikely((state | 3) == 0x1bf)) pos = find_end(&buf, pos, demux->stream); } while (++pos < 0); demux->priv = (void *)state; len = buf - pack->buffer; } if (len < STREAM_BUFFER_SIZE) resize_demux_packet(pack, len); ds_add_packet(ds, pack); return 1;}int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds){unsigned int head=0;int skipped=0;int max_packs=256; // 512kbyteint ret=0;// System streamdo{ demux->filepos=stream_tell(demux->stream);#if 1 //lame workaround: this is needed to show the progress bar when playing dvdnav:// //(ths poor guy doesn't know teh length of the stream at startup) demux->movi_end = demux->stream->end_pos;#endif head=stream_read_dword(demux->stream); if((head&0xFFFFFF00)!=0x100){ // sync... demux->filepos-=skipped; while(1){ int c=stream_read_char(demux->stream); if(c<0) break; //EOF head<<=8; if(head!=0x100){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -