⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demux_mpg.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 3 页
字号:
//  MPG/VOB file parser for DEMUXER v2.5  by A'rpi/ESP-team#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <math.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream/stream.h"#include "demuxer.h"#include "parse_es.h"#include "stheader.h"#include "mp3_hdr.h"//#define MAX_PS_PACKETSIZE 2048#define MAX_PS_PACKETSIZE (224*1024)#define UNKNOWN         0#define VIDEO_MPEG1     0x10000001#define VIDEO_MPEG2     0x10000002#define VIDEO_MPEG4     0x10000004#define VIDEO_H264      0x10000005#define AUDIO_MP2       0x50#define AUDIO_A52       0x2000#define AUDIO_LPCM_BE   0x10001#define AUDIO_AAC       mmioFOURCC('M', 'P', '4', 'A')typedef struct mpg_demuxer {  float last_pts;  float first_pts;              // first pts found in stream  float first_to_final_pts_len; // difference between final pts and first pts  int has_valid_timestamps;     // !=0 iff time stamps look linear                                // (not necessarily starting with 0)  unsigned int es_map[0x40];	//es map of stream types (associated to the pes id) from 0xb0 to 0xef  int num_a_streams;  int a_stream_ids[MAX_A_STREAMS];} mpg_demuxer_t;extern char* dvdsub_lang;static int mpeg_pts_error=0;off_t ps_probe = 0;static int parse_psm(demuxer_t *demux, int len) {  unsigned char c, id, type;  unsigned int plen, prog_len, es_map_len;  mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;    mp_dbg(MSGT_DEMUX,MSGL_V, "PARSE_PSM, len=%d\n", len);  if(! len || len > 1018)    return 0;    c = stream_read_char(demux->stream);  if(! (c & 0x80)) {    stream_skip(demux->stream, len - 1);  //not yet valid, discard    return 0;  }  stream_skip(demux->stream, 1);  prog_len = stream_read_word(demux->stream);		//length of program descriptors  stream_skip(demux->stream, prog_len);			//.. that we ignore  es_map_len = stream_read_word(demux->stream);		//length of elementary streams map  es_map_len = FFMIN(es_map_len, len - prog_len - 8);	//sanity check  while(es_map_len > 0) {    type = stream_read_char(demux->stream);    id = stream_read_char(demux->stream);    if(id >= 0xB0 && id <= 0xEF && priv) {      int idoffset = id - 0xB0;      switch(type) {        case 0x1:          priv->es_map[idoffset] = VIDEO_MPEG1;          break;        case 0x2:          priv->es_map[idoffset] = VIDEO_MPEG2;          break;        case 0x3:        case 0x4:          priv->es_map[idoffset] = AUDIO_MP2;          break;        case 0x0f:        case 0x11:          priv->es_map[idoffset] = AUDIO_AAC;          break;        case 0x10:          priv->es_map[idoffset] = VIDEO_MPEG4;          break;        case 0x1b:          priv->es_map[idoffset] = VIDEO_H264;          break;        case 0x81:          priv->es_map[idoffset] = AUDIO_A52;          break;      }      mp_dbg(MSGT_DEMUX,MSGL_V, "PSM ES, id=0x%x, type=%x, stype: %x\n", id, type, priv->es_map[idoffset]);    }    plen = stream_read_word(demux->stream);		//length of elementary stream descriptors    plen = FFMIN(plen, es_map_len);			//sanity check    stream_skip(demux->stream, plen);			//skip descriptors for now    es_map_len -= 4 + plen;  }  stream_skip(demux->stream, 4);			//skip crc32  return 1;}// 500000 is a wild guess#define TIMESTAMP_PROBE_LEN 500000//MAX_PTS_DIFF_FOR_CONSECUTIVE denotes the maximum difference//between two pts to consider them consecutive//1.0 is a wild guess#define MAX_PTS_DIFF_FOR_CONSECUTIVE 1.0//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream.//if no pts is found or an error occurs, -1.0 is returned.//Packs are freed.static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos){  stream_t *s = demuxer->stream;  mpg_demuxer_t *mpg_d = demuxer->priv;  float pts = -1.0; //the pts to return;  float found_pts1; //the most recently found pts  float found_pts2; //the pts found before found_pts1  float found_pts3; //the pts found before found_pts2  int found = 0;  if(!mpg_d || stream_pos < 0)    return pts;  found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts;  stream_seek(s, stream_pos);  //We look for pts.  //However, we do not stop at the first found one, as timestamps may reset  //Therefore, we seek until we found three consecutive  //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE.  while(found<3 && !s->eof   && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE)   && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE)   && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN)   && ds_fill_buffer(demuxer->video))  {    if(mpg_d->last_pts != found_pts1)    {      if(!found)        found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts      else      {        found_pts3 = found_pts2;        found_pts2 = found_pts1;        found_pts1 = mpg_d->last_pts;      }      found++;    }  }  if(found == 3) pts = found_pts3;  //clean up from searching of first pts;  ds_free_packs(demuxer->audio);  ds_free_packs(demuxer->video);  ds_free_packs(demuxer->sub);  return pts;}/// Open an mpg physical streamstatic demuxer_t* demux_mpg_open(demuxer_t* demuxer) {  stream_t *s = demuxer->stream;  mpg_demuxer_t* mpg_d;  if (!ds_fill_buffer(demuxer->video)) return 0;  mpg_d = calloc(1,sizeof(mpg_demuxer_t));  if(mpg_d)  {    demuxer->priv = mpg_d;    mpg_d->last_pts = -1.0;    mpg_d->first_pts = -1.0;    //if seeking is allowed set has_valid_timestamps if appropriate    if(demuxer->seekable       && (demuxer->stream->type == STREAMTYPE_FILE           || demuxer->stream->type == STREAMTYPE_VCD)       && demuxer->movi_start != demuxer-> movi_end    )    {      //We seek to the beginning of the stream, to somewhere in the      //middle, and to the end of the stream, while remembering the pts      //at each of the three positions. With these pts, we check whether      //or not the pts are "linear enough" to justify seeking by the pts      //of the stream      //The position where the stream is now      off_t pos = stream_tell(s);      float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);      if(first_pts != -1.0)      {        float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);        if(middle_pts != -1.0)        {          float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);          if(final_pts != -1.0)          {            // found proper first, middle, and final pts.            float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);            // if they are linear enough set has_valid_timestamps            if((0.5 < proportion) && (proportion < 2))            {              mpg_d->first_pts = first_pts;              mpg_d->first_to_final_pts_len = final_pts - first_pts;              mpg_d->has_valid_timestamps = 1;            }          }        }      }      //Cleaning up from seeking in stream      demuxer->stream->eof=0;      demuxer->video->eof=0;      demuxer->audio->eof=0;      stream_seek(s,pos);      ds_fill_buffer(demuxer->video);    } // if ( demuxer->seekable )  } // if ( mpg_d )  return demuxer;}static void demux_close_mpg(demuxer_t* demuxer) {  mpg_demuxer_t* mpg_d = demuxer->priv;  if (mpg_d) free(mpg_d);}static unsigned long long read_mpeg_timestamp(stream_t *s,int c){  unsigned int d,e;  unsigned long long pts;  d=stream_read_word(s);  e=stream_read_word(s);  if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){    ++mpeg_pts_error;    return 0; // invalid pts  }  pts=(((uint64_t)((c>>1)&7))<<30)|((d>>1)<<15)|(e>>1);  mp_dbg(MSGT_DEMUX,MSGL_DBG3," pts {%"PRIu64"}",pts);  return pts;}static void new_audio_stream(demuxer_t *demux, int aid){  if(!demux->a_streams[aid]){    mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demux->priv;    sh_audio_t* sh_a;    new_sh_audio(demux,aid);    sh_a = (sh_audio_t*)demux->a_streams[aid];    switch(aid & 0xE0){  // 1110 0000 b  (high 3 bit: type  low 5: id)      case 0x00: sh_a->format=0x50;break; // mpeg      case 0xA0: sh_a->format=0x10001;break;  // dvd pcm      case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts                  else sh_a->format=0x2000;break; // ac3    }    //evo files    if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;    else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;    if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;  }  if(demux->audio->id==-1) demux->audio->id=aid;}static int demux_mpg_read_packet(demuxer_t *demux,int id){  int d;  int len;  int set_pts=0; // !=0 iff pts has been set to a proper value  unsigned char c=0;  unsigned long long pts=0;  unsigned long long dts=0;  int l;  int pes_ext2_subid=-1;  double stream_pts = MP_NOPTS_VALUE;  demux_stream_t *ds=NULL;  demux_packet_t* dp;  mpg_demuxer_t *priv = (mpg_demuxer_t *) demux->priv;  mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id);//  if(id==0x1F0){//    demux->synced=0; // force resync after 0x1F0//    return -1;//}//  if(id==0x1BA) packet_start_pos=stream_tell(demux->stream);  if((id<0x1BC || id>=0x1F0) && id != 0x1FD) return -1;  if(id==0x1BE) return -1; // padding stream  if(id==0x1BF) return -1; // private2  len=stream_read_word(demux->stream);  mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len);//  if(len==62480){ demux->synced=0;return -1;} /* :) */  if(len==0 || len>MAX_PS_PACKETSIZE){    mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len);    return -2;  // invalid packet !!!!!!  }  mpeg_pts_error=0;  if(id==0x1BC) {    parse_psm(demux, len);    return 0;  }  while(len>0){   // Skip stuFFing bytes    c=stream_read_char(demux->stream);    --len;    if(c!=0xFF)break;  }  if((c>>6)==1){  // Read (skip) STD scale & size value//    printf("  STD_scale=%d",(c>>5)&1);    d=((c&0x1F)<<8)|stream_read_char(demux->stream);    len-=2;//    printf("  STD_size=%d",d);    c=stream_read_char(demux->stream);  }  // Read System-1 stream timestamps:  if((c>>4)==2){    pts=read_mpeg_timestamp(demux->stream,c);    set_pts=1;    len-=4;  } else  if((c>>4)==3){    pts=read_mpeg_timestamp(demux->stream,c);    c=stream_read_char(demux->stream);    if((c>>4)!=1) pts=0; //printf("{ERROR4}");    else set_pts = 1;    dts=read_mpeg_timestamp(demux->stream,c);    len-=4+1+4;  } else  if((c>>6)==2){    int pts_flags;    int hdrlen;    int parse_ext2;    // System-2 (.VOB) stream:    c=stream_read_char(demux->stream);    pts_flags=c>>6;    parse_ext2 = (id == 0x1FD) && ((c & 0x3F) == 1);    c=stream_read_char(demux->stream);    hdrlen=c;    len-=2;    mp_dbg(MSGT_DEMUX,MSGL_DBG3,"  hdrlen=%d  (len=%d)",hdrlen,len);    if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length  \n"); return -1;}    if(pts_flags==2 && hdrlen>=5){      c=stream_read_char(demux->stream);      pts=read_mpeg_timestamp(demux->stream,c);      set_pts=1;      len-=5;hdrlen-=5;    } else    if(pts_flags==3 && hdrlen>=10){      c=stream_read_char(demux->stream);      pts=read_mpeg_timestamp(demux->stream,c);      set_pts=1;      c=stream_read_char(demux->stream);      dts=read_mpeg_timestamp(demux->stream,c);      len-=10;hdrlen-=10;    }    len-=hdrlen;    if(parse_ext2 && hdrlen>=3) {      c=stream_read_char(demux->stream);      hdrlen--;      if((c & 0x0F) != 0x0F) {        mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: pes_extension_flag2 not set, discarding pes packet\n");        return -1;      }      if(c & 0x80) { //pes_private_data_flag        if(hdrlen<16) {          mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pes_private_data bytes: %d < 16, discarding pes packet\n", hdrlen);          return -1;        }        stream_skip(demux->stream, 16);        hdrlen-=16;      }      if(c & 0x40) { //pack_header_field_flag        int l = stream_read_char(demux->stream);        if(l < 0) //couldn't read from the stream?          return -1;        hdrlen--;        if(l < 0 || hdrlen < l) {          mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough pack_header bytes: hdrlen: %d < skip: %d, discarding pes packet\n",                                   hdrlen, l);          return -1;        }        stream_skip(demux->stream, l);        hdrlen-=l;      }      if(c & 0x20) { //program_packet_sequence_counter_flag        if(hdrlen < 2) {          mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: not enough program_packet bytes: hdrlen: %d, discarding pes packet\n", hdrlen);          return -1;        }        stream_skip(demux->stream, 2);        hdrlen-=2;      }      if(c & 0x10) {        //STD        stream_skip(demux->stream, 2);        hdrlen-=2;      }      c=stream_read_char(demux->stream); //pes_extension2 flag      hdrlen--;      if(c!=0x81)  { mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: unknown pes_extension2 format, len is > 1  \n"); return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -