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

📄 demux_avi.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
//  AVI file parser for DEMUXER v2.9  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 "stheader.h"#include "aviheader.h"// PTS:  0=interleaved  1=BPS-basedint pts_from_bps=1;// Select ds from IDdemux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){  int stream_id=avi_stream_id(id);//  printf("demux_avi_select_stream(%d)  {a:%d/v:%d}\n",stream_id,//       demux->audio->id,demux->video->id);  if(demux->video->id==-1)    if(demux->v_streams[stream_id])        demux->video->id=stream_id;  if(demux->audio->id==-1)    if(demux->a_streams[stream_id])        demux->audio->id=stream_id;  if(stream_id==demux->audio->id){      if(!demux->audio->sh){        sh_audio_t* sh;	avi_priv_t *priv=demux->priv;        sh=demux->audio->sh=demux->a_streams[stream_id];        mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id);	if(sh->wf){	  priv->audio_block_size=sh->wf->nBlockAlign;	  if(!priv->audio_block_size){	    // for PCM audio we can calculate the blocksize:	    if(sh->format==1)		priv->audio_block_size=sh->wf->nChannels*(sh->wf->wBitsPerSample/8);	    else		priv->audio_block_size=1; // hope the best...	  } else {	    // workaround old mencoder's bug:	    if(sh->audio.dwSampleSize==1 && sh->audio.dwScale==1 &&	       (sh->wf->nBlockAlign==1152 || sh->wf->nBlockAlign==576)){		mp_msg(MSGT_DEMUX,MSGL_WARN,"AVI: Workarounding CBR-MP3 nBlockAlign header bug!\n");		priv->audio_block_size=1;	    }	  }	} else {	  priv->audio_block_size=sh->audio.dwSampleSize;	}//	printf("&&&&& setting blocksize to %d &&&&&\n",priv->audio_block_size);      }      return demux->audio;  }  if(stream_id==demux->video->id){      if(!demux->video->sh){        demux->video->sh=demux->v_streams[stream_id];        mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI video ID = %d\n",demux->video->id);      }      return demux->video;  }  if(id!=mmioFOURCC('J','U','N','K')){     // unknown     mp_msg(MSGT_DEMUX,MSGL_DBG2,"Unknown chunk: %.4s (%X)\n",(char *) &id,id);     //abort();  }  return NULL;}static int valid_fourcc(unsigned int id){    unsigned char* fcc=(unsigned char*)(&id);#define FCC_CHR_CHECK(x) (x<48 || x>=96)    if(FCC_CHR_CHECK(fcc[0])) return 0;    if(FCC_CHR_CHECK(fcc[1])) return 0;    if(FCC_CHR_CHECK(fcc[2])) return 0;    if(FCC_CHR_CHECK(fcc[3])) return 0;    return 1;#undef FCC_CHR_CHECK}static int choose_chunk_len(unsigned int len1,unsigned int len2){    // len1 has a bit more priority than len2. len1!=len2    // Note: this is a first-idea-logic, may be wrong. comments welcomed.    // prefer small frames rather than 0    if(!len1) return (len2>0x80000) ? len1 : len2;    if(!len2) return (len1>0x100000) ? len2 : len1;    // choose the smaller value:    return (len1<len2)? len1 : len2;}static int demux_avi_read_packet(demuxer_t *demux,demux_stream_t *ds,unsigned int id,unsigned int len,int idxpos,int flags){  avi_priv_t *priv=demux->priv;  int skip;  float pts=0;    mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id);  if(ds==demux->audio){      if(priv->pts_corrected==0){//          printf("\rYYY-A  A: %5.3f  V: %5.3f  \n",priv->avi_audio_pts,priv->avi_video_pts);          if(priv->pts_has_video){	      // we have video pts now	      float delay=0;	      if(((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec)	          delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;	      mp_msg(MSGT_DEMUX,MSGL_V,"XXX initial  v_pts=%5.3f  a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay);	      //priv->pts_correction=-priv->avi_audio_pts+delay;	      priv->pts_correction=delay-priv->avi_audio_pts;	      priv->avi_audio_pts+=priv->pts_correction;	      priv->pts_corrected=1;	  } else	      priv->pts_corr_bytes+=len;      }      if(pts_from_bps){	  pts = priv->audio_block_no *	    (float)((sh_audio_t*)demux->audio->sh)->audio.dwScale /	    (float)((sh_audio_t*)demux->audio->sh)->audio.dwRate;      } else          pts=priv->avi_audio_pts; //+priv->pts_correction;      priv->avi_audio_pts=0;      // update blockcount:      priv->audio_block_no+=priv->audio_block_size ?	((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;//      printf("\raudio_block_no=%d      \n",priv->audio_block_no);  } else   if(ds==demux->video){     // video     if(priv->skip_video_frames>0){       // drop frame (seeking)       --priv->skip_video_frames;       ds=NULL;     }     pts = priv->avi_video_pts = priv->video_pack_no *         (float)((sh_video_t*)demux->video->sh)->video.dwScale /	 (float)((sh_video_t*)demux->video->sh)->video.dwRate;//          printf("\rYYY-V  A: %5.3f  V: %5.3f  \n",priv->avi_audio_pts,priv->avi_video_pts);     priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;     priv->pts_has_video=1;     if(ds) ++priv->video_pack_no;     //printf("read  pack_no: %d  pts %5.3f  \n",demux->video->pack_no+demux->video->packs,pts);  }    skip=(len+1)&(~1); // total bytes in this chunk    if(ds){    mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id);//    printf("READ[%c] %5.3f  (%d)   \n",ds==demux->video?'V':'A',pts,len);    ds_read_packet(ds,demux->stream,len,pts,idxpos,flags);    skip-=len;  }  if(skip){    mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id);    stream_skip(demux->stream,skip);  }  return ds?1:0;}// return value://     0 = EOF or no stream found//     1 = successfully read a packetint demux_avi_fill_buffer(demuxer_t *demux){avi_priv_t *priv=demux->priv;unsigned int id=0;unsigned int len;//int max_packs=128;int ret=0;demux_stream_t *ds;do{  int flags=1;  AVIINDEXENTRY *idx=NULL;#if 0  demux->filepos=stream_tell(demux->stream);  if(demux->filepos>=demux->movi_end){          demux->stream->eof=1;          return 0;  }  if(stream_eof(demux->stream)) return 0;#endif  if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){    off_t pos;        //if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos);        idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];        //printf("[%d]",priv->idx_pos);fflush(stdout);        //stream_seek(demux->stream,idx.dwChunkOffset);    //printf("IDX  pos=%X  idx.pos=%X  idx.size=%X  idx.flags=%X\n",demux->filepos,    //  pos-4,idx->dwChunkLength,idx->dwFlags);    if(idx->dwFlags&AVIIF_LIST){      // LIST      continue;    }    if(!demux_avi_select_stream(demux,idx->ckid)){      mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X)  \n",(char *)&idx->ckid,(unsigned int)idx->ckid);      continue; // skip this chunk    }    pos = (off_t)priv->idx_offset+AVI_IDX_OFFSET(idx);    if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start) && (demux->stream->flags & STREAM_SEEK)){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range!   idx=0x%X  \n",pos);      continue;    }#if 0    if(pos!=demux->filepos){      mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X  idx.pos=0x%X  diff=%d   \n",demux->filepos,pos,pos-demux->filepos);    }#endif    stream_seek(demux->stream,pos);    demux->filepos=stream_tell(demux->stream);    id=stream_read_dword_le(demux->stream);    if(stream_eof(demux->stream)) return 0; // EOF!        if(id!=idx->ckid){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s  \n",(char *)&id,(char *)&idx->ckid);      if(valid_fourcc(idx->ckid))          id=idx->ckid;	// use index if valid      else          if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad    }    len=stream_read_dword_le(demux->stream);//    if((len&(~1))!=(idx->dwChunkLength&(~1))){//    if((len)!=(idx->dwChunkLength)){    if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld  \n",len,idx->dwChunkLength);      if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(      len=choose_chunk_len(idx->dwChunkLength,len);    }    if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;  } else {    demux->filepos=stream_tell(demux->stream);    if(demux->filepos>=demux->movi_end && demux->movi_end>demux->movi_start && (demux->stream->flags & STREAM_SEEK)){          demux->stream->eof=1;          return 0;    }    id=stream_read_dword_le(demux->stream);    len=stream_read_dword_le(demux->stream);    if(stream_eof(demux->stream)) return 0; // EOF!        if(id==mmioFOURCC('L','I','S','T') || id==mmioFOURCC('R', 'I', 'F', 'F')){      id=stream_read_dword_le(demux->stream); // list or RIFF type      continue;    }  }  ds=demux_avi_select_stream(demux,id);  if(ds)    if(ds->packs+1>=MAX_PACKS || ds->bytes+len>=MAX_PACK_BYTES){	// this packet will cause a buffer overflow, switch to -ni mode!!!	mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_SwitchToNi);	if(priv->idx_size>0){	    // has index	    demux->type=DEMUXER_TYPE_AVI_NI;	    --priv->idx_pos; // hack	} else {	    // no index	    demux->type=DEMUXER_TYPE_AVI_NINI;	    priv->idx_pos=demux->filepos; // hack	}	priv->idx_pos_v=priv->idx_pos_a=priv->idx_pos;	// quit now, we can't even (no enough buffer memory) read this packet :(	return -1;    }    ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,flags);//      if(!ret && priv->skip_video_frames<=0)//        if(--max_packs==0){//          demux->stream->eof=1;//          mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream);//          return 0;//        }} while(ret!=1);  return 1;}// return value://     0 = EOF or no stream found//     1 = successfully read a packetint demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){avi_priv_t *priv=demux->priv;unsigned int id=0;unsigned int len;//int max_packs=128;int ret=0;do{  int flags=1;  AVIINDEXENTRY *idx=NULL;  int idx_pos=0;  demux->filepos=stream_tell(demux->stream);    if(ds==demux->video) idx_pos=priv->idx_pos_v++; else  if(ds==demux->audio) idx_pos=priv->idx_pos_a++; else                       idx_pos=priv->idx_pos++;    if(priv->idx_size>0 && idx_pos<priv->idx_size){    off_t pos;    idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];//    idx=&priv->idx[idx_pos];        if(idx->dwFlags&AVIIF_LIST){      // LIST      continue;    }    if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){      mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X)  \n",(char *)&idx->ckid,(unsigned int)idx->ckid);      continue; // skip this chunk    }    pos = priv->idx_offset+AVI_IDX_OFFSET(idx);    if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start)){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range!  current=0x%X  idx=0x%X  \n",demux->filepos,pos);      continue;    }#if 0    if(pos!=demux->filepos){      mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X  idx.pos=0x%X  diff=%d   \n",demux->filepos,pos,pos-demux->filepos);    }#endif    stream_seek(demux->stream,pos);    id=stream_read_dword_le(demux->stream);    if(stream_eof(demux->stream)) return 0;    if(id!=idx->ckid){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s  \n",(char *)&id,(char *)&idx->ckid);      if(valid_fourcc(idx->ckid))          id=idx->ckid;	// use index if valid      else          if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad    }    len=stream_read_dword_le(demux->stream);    if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){      mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld  \n",len,idx->dwChunkLength);      if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(      len=choose_chunk_len(idx->dwChunkLength,len);    }    if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;  } else return 0;  ret=demux_avi_read_packet(demux,demux_avi_select_stream(demux,id),id,len,idx_pos,flags);//      if(!ret && priv->skip_video_frames<=0)//        if(--max_packs==0){//          demux->stream->eof=1;//          mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream);//          return 0;//        }} while(ret!=1);  return 1;}// return value://     0 = EOF or no stream found//     1 = successfully read a packetint demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){avi_priv_t *priv=demux->priv;unsigned int id=0;unsigned int len;int ret=0;off_t *fpos=NULL;  if(ds==demux->video) fpos=&priv->idx_pos_v; else  if(ds==demux->audio) fpos=&priv->idx_pos_a; else  return 0;  stream_seek(demux->stream,fpos[0]);do{  demux->filepos=stream_tell(demux->stream);  if(demux->filepos>=demux->movi_end && (demux->movi_end>demux->movi_start)){          //demux->stream->eof=1;	  ds->eof=1;          return 0;  }  id=stream_read_dword_le(demux->stream);  len=stream_read_dword_le(demux->stream);  if(stream_eof(demux->stream)) return 0;    if(id==mmioFOURCC('L','I','S','T')){      id=stream_read_dword_le(demux->stream);      // list type      continue;  }    if(id==mmioFOURCC('R','I','F','F')){      mp_msg(MSGT_DEMUX,MSGL_V,"additional RIFF header...\n");      id=stream_read_dword_le(demux->stream);      // "AVIX"      continue;  }    if(ds==demux_avi_select_stream(demux,id)){    // read it!    ret=demux_avi_read_packet(demux,ds,id,len,priv->idx_pos-1,0);  } else {    // skip it!    int skip=(len+1)&(~1); // total bytes in this chunk    stream_skip(demux->stream,skip);  }  } while(ret!=1);  fpos[0]=stream_tell(demux->stream);  return 1;}// AVI demuxer parameters:int index_mode=-1;  // -1=untouched  0=don't use index  1=use (geneate) indexchar *index_file_save = NULL, *index_file_load = NULL;int force_ni=0;     // force non-interleaved AVI parsing

⌨️ 快捷键说明

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