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

📄 demux_mpg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
//  MPG/VOB file parser for DEMUXER v2.5  by A'rpi/ESP-team#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "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 final_pts;  int has_valid_timestamps;  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;static int mpeg_pts_error=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)    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 = min(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 = min(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;}/// Open an mpg physical streamint demux_mpg_open(demuxer_t* demuxer) {  stream_t *s = demuxer->stream;  off_t pos = stream_tell(s);  off_t end_seq_start = demuxer->movi_end-500000; // 500000 is a wild guess  float half_pts = 0.0;  mpg_demuxer_t* mpg_d;  if (!ds_fill_buffer(demuxer->video)) return 0;  mpg_d = (mpg_demuxer_t*)calloc(1,sizeof(mpg_demuxer_t));  demuxer->priv = mpg_d;  mpg_d->final_pts = 0.0;  mpg_d->has_valid_timestamps = 1;  mpg_d->num_a_streams = 0;  if (demuxer->seekable && stream_tell(demuxer->stream) < end_seq_start) {    stream_seek(s,(pos + end_seq_start / 2));    while ((!s->eof) && ds_fill_buffer(demuxer->video) && half_pts == 0.0) {      half_pts = mpg_d->last_pts;    }    stream_seek(s,end_seq_start);    while ((!s->eof) && ds_fill_buffer(demuxer->video)) {      if (mpg_d->final_pts < mpg_d->last_pts) mpg_d->final_pts = mpg_d->last_pts;    }    // educated guess about validity of timestamps    if (mpg_d->final_pts > 3 * half_pts || mpg_d->final_pts < 1.5 * half_pts) {      mpg_d->has_valid_timestamps = 0;    }    ds_free_packs(demuxer->audio);    ds_free_packs(demuxer->video);    demuxer->stream->eof=0; // clear eof flag    demuxer->video->eof=0;    demuxer->audio->eof=0;        stream_seek(s,pos);    ds_fill_buffer(demuxer->video);  }  return 1;}void demux_close_mpg(demuxer_t* demuxer) {  mpg_demuxer_t* mpg_d = demuxer->priv;  if (mpg_d) free(mpg_d);}static unsigned int read_mpeg_timestamp(stream_t *s,int c){  int d,e;  unsigned int 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=(((c>>1)&7)<<30)|((d>>1)<<15)|(e>>1);  mp_dbg(MSGT_DEMUX,MSGL_DBG3,"{%d}",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    }    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;  unsigned char c=0;  unsigned int pts=0;  unsigned int dts=0;  demux_stream_t *ds=NULL;  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) 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);    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}");    dts=read_mpeg_timestamp(demux->stream,c);    len-=4+1+4;  } else  if((c>>6)==2){    int pts_flags;    int hdrlen;    // System-2 (.VOB) stream:    if((c>>4)&3) {        mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_EncryptedVOB);    }    c=stream_read_char(demux->stream); pts_flags=c>>6;    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);      len-=5;hdrlen-=5;    } else    if(pts_flags==3 && hdrlen>=10){      c=stream_read_char(demux->stream);      pts=read_mpeg_timestamp(demux->stream,c);      c=stream_read_char(demux->stream);      dts=read_mpeg_timestamp(demux->stream,c);      len-=10;hdrlen-=10;    }    len-=hdrlen;    if(hdrlen>0) stream_skip(demux->stream,hdrlen); // skip header bytes        //============== DVD Audio sub-stream ======================    if(id==0x1BD){      int aid=stream_read_char(demux->stream);--len;      if(len<3) return -1; // invalid audio packet            // AID:      // 0x20..0x3F  subtitle      // 0x80..0x9F  AC3 audio      // 0xA0..0xBF  PCM audio            if((aid & 0xE0) == 0x20){        // subtitle:        aid&=0x1F;        if(!demux->s_streams[aid]){            mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);            demux->s_streams[aid]=1;        }        if(demux->sub->id==aid){            ds=demux->sub;        }                } else if((aid & 0xC0) == 0x80 || (aid & 0xE0) == 0x00) {//        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:        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))->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 !!!!!!    }

⌨️ 快捷键说明

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