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

📄 demux_avi.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
void read_avi_header(demuxer_t *demuxer,int index_mode);demuxer_t* demux_open_avi(demuxer_t* demuxer){    demux_stream_t *d_audio=demuxer->audio;    demux_stream_t *d_video=demuxer->video;    sh_audio_t *sh_audio=NULL;    sh_video_t *sh_video=NULL;    avi_priv_t* priv=malloc(sizeof(avi_priv_t));  // priv struct:  priv->avi_audio_pts=priv->avi_video_pts=0.0f;  priv->pts_correction=0.0f;  priv->skip_video_frames=0;  priv->pts_corr_bytes=0;  priv->pts_has_video=priv->pts_corrected=0;  priv->video_pack_no=0;  priv->audio_block_no=0;  priv->audio_block_size=0;  priv->isodml = 0;  priv->suidx_size = 0;  priv->suidx = NULL;  demuxer->priv=(void*)priv;  //---- AVI header:  read_avi_header(demuxer,(demuxer->stream->flags & STREAM_SEEK_BW)?index_mode:-2);    if(demuxer->audio->id>=0 && !demuxer->a_streams[demuxer->audio->id]){      mp_msg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid audio stream ID: %d - ignoring (nosound)\n",demuxer->audio->id);      demuxer->audio->id=-2; // disabled  }  if(demuxer->video->id>=0 && !demuxer->v_streams[demuxer->video->id]){      mp_msg(MSGT_DEMUX,MSGL_WARN,"AVI: invalid video stream ID: %d - ignoring (using default)\n",demuxer->video->id);      demuxer->video->id=-1; // autodetect  }    stream_reset(demuxer->stream);  stream_seek(demuxer->stream,demuxer->movi_start);  priv->idx_pos=0;  priv->idx_pos_a=0;  priv->idx_pos_v=0;  if(priv->idx_size>1){    // decide index format:#if 1    if((AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start ||        AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[1])<demuxer->movi_start )&& !priv->isodml)      priv->idx_offset=demuxer->movi_start-4;    else      priv->idx_offset=0;#else    if(AVI_IDX_OFFSET(&((AVIINDEXENTRY *)priv->idx)[0])<demuxer->movi_start)      priv->idx_offset=demuxer->movi_start-4;    else      priv->idx_offset=0;#endif    mp_msg(MSGT_DEMUX,MSGL_V,"AVI index offset: 0x%X (movi=0x%X idx0=0x%X idx1=0x%X)\n",	    (int)priv->idx_offset,(int)demuxer->movi_start,	    (int)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset,	    (int)((AVIINDEXENTRY *)priv->idx)[1].dwChunkOffset);  }//  demuxer->endpos=avi_header.movi_end;    if(priv->idx_size>0){      // check that file is non-interleaved:      int i;      off_t a_pos=-1;      off_t v_pos=-1;      for(i=0;i<priv->idx_size;i++){        AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];        demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);        off_t pos = priv->idx_offset + AVI_IDX_OFFSET(idx);        if(a_pos==-1 && ds==demuxer->audio){          a_pos=pos;          if(v_pos!=-1) break;        }        if(v_pos==-1 && ds==demuxer->video){          v_pos=pos;          if(a_pos!=-1) break;        }      }      if(v_pos==-1){        mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI_NI: " MSGTR_MissingVideoStream);	return NULL;      }      if(a_pos==-1){        mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI_NI: " MSGTR_MissingAudioStream);        sh_audio=NULL;      } else {        if(force_ni || abs(a_pos-v_pos)>0x100000){  // distance > 1MB          mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_NI_Message,force_ni?MSGTR_NI_Forced:MSGTR_NI_Detected);          demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!	  pts_from_bps=1; // force BPS sync!        }      }  } else {      // no index      if(force_ni){          mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_UsingNINI);          demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!	  priv->idx_pos_a=	  priv->idx_pos_v=demuxer->movi_start;	  pts_from_bps=1; // force BPS sync!      }      demuxer->seekable=0;  }  if(!ds_fill_buffer(d_video)){    mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI: " MSGTR_MissingVideoStreamBug);    return NULL;  }  sh_video=d_video->sh;sh_video->ds=d_video;  if(d_audio->id!=-2){    mp_msg(MSGT_DEMUX,MSGL_V,"AVI: Searching for audio stream (id:%d)\n",d_audio->id);    if(!priv->audio_streams || !ds_fill_buffer(d_audio)){      mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI: " MSGTR_MissingAudioStream);      sh_audio=NULL;    } else {      sh_audio=d_audio->sh;sh_audio->ds=d_audio;      sh_audio->format=sh_audio->wf->wFormatTag;    }  }  // calc. FPS:  sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;  sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;  // calculating audio/video bitrate:  if(priv->idx_size>0){    // we have index, let's count 'em!    size_t vsize=0;    size_t asize=0;    size_t vsamples=0;    size_t asamples=0;    int i;    for(i=0;i<priv->idx_size;i++){       int id=avi_stream_id(((AVIINDEXENTRY *)priv->idx)[i].ckid);      int len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;      if(sh_video->ds->id == id) {        vsize+=len;        ++vsamples;      }      else if(sh_audio && sh_audio->ds->id == id) {        asize+=len;	asamples+=(len+priv->audio_block_size-1)/priv->audio_block_size;      }    }    mp_msg(MSGT_DEMUX,MSGL_V,"AVI video size=%lu (%lu) audio size=%lu (%lu)\n",vsize,vsamples,asize,asamples);    priv->numberofframes=vsamples;    sh_video->i_bps=((float)vsize/(float)vsamples)*(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;    if(sh_audio) sh_audio->i_bps=((float)asize/(float)asamples)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;  } else {    // guessing, results may be inaccurate:    size_t vsize;    size_t asize=0;    if((priv->numberofframes=sh_video->video.dwLength)<=1)      // bad video header, try to get number of frames from audio      if(sh_audio && sh_audio->wf->nAvgBytesPerSec) priv->numberofframes=sh_video->fps*sh_audio->audio.dwLength/sh_audio->audio.dwRate*sh_audio->audio.dwScale;    if(priv->numberofframes<=1){      mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CouldntDetFNo);      priv->numberofframes=0;    }              if(sh_audio){      if(sh_audio->wf->nAvgBytesPerSec && sh_audio->audio.dwSampleSize!=1){        asize=(float)sh_audio->wf->nAvgBytesPerSec*sh_audio->audio.dwLength*sh_audio->audio.dwScale/sh_audio->audio.dwRate;        sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;      } else {        asize=sh_audio->audio.dwLength;        sh_audio->i_bps=(float)asize/(sh_video->frametime*priv->numberofframes);      }    }    vsize=demuxer->movi_end-demuxer->movi_start-asize-8*priv->numberofframes;    mp_msg(MSGT_DEMUX,MSGL_V,"AVI video size=%lu (%lu)  audio size=%lu\n",vsize,priv->numberofframes,asize);    sh_video->i_bps=(float)vsize/(sh_video->frametime*priv->numberofframes);  }  mp_msg(MSGT_DEMUX,MSGL_INFO,"VIDEO:  [%.4s]  %ldx%ld  %dbpp  %5.3f fps  %5.1f kbps (%4.1f kbyte/s)\n",    (char *)&sh_video->bih->biCompression,    sh_video->bih->biWidth,    sh_video->bih->biHeight,    sh_video->bih->biBitCount,    sh_video->fps,    sh_video->i_bps*0.008f,    sh_video->i_bps/1024.0f );  return demuxer;  }//extern float initial_pts_delay;extern void resync_audio_stream(sh_audio_t *sh_audio);void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){    avi_priv_t *priv=demuxer->priv;    demux_stream_t *d_audio=demuxer->audio;    demux_stream_t *d_video=demuxer->video;    sh_audio_t *sh_audio=d_audio->sh;    sh_video_t *sh_video=d_video->sh;    float skip_audio_secs=0;  //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?)  //================= seek in AVI ==========================    int rel_seek_frames=rel_seek_secs*sh_video->fps;    int video_chunk_pos=d_video->pos;    int i;      if(flags&1){	// seek absolute	video_chunk_pos=0;      }            if(flags&2){	rel_seek_frames=rel_seek_secs*priv->numberofframes;      }          priv->skip_video_frames=0;      priv->avi_audio_pts=0;// ------------ STEP 1: find nearest video keyframe chunk ------------      // find nearest video keyframe chunk pos:      if(rel_seek_frames>0){        // seek forward        while(video_chunk_pos<priv->idx_size-1){          int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;          if(avi_stream_id(id)==d_video->id){  // video frame            if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;          }          ++video_chunk_pos;        }      } else {        // seek backward        while(video_chunk_pos>0){          int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;          if(avi_stream_id(id)==d_video->id){  // video frame            if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;          }          --video_chunk_pos;        }      }      priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=video_chunk_pos;      // re-calc video pts:      d_video->pack_no=0;      for(i=0;i<video_chunk_pos;i++){          int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;          if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;      }      priv->video_pack_no=      sh_video->num_frames=sh_video->num_frames_decoded=d_video->pack_no;      priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;      d_video->pos=video_chunk_pos;            mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK:  pack=%d  pts=%5.3f  chunk=%d  \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos);// ------------ STEP 2: seek audio, find the right chunk & pos ------------      d_audio->pack_no=0;//      d_audio->block_no=0;      priv->audio_block_no=0;      d_audio->dpos=0;      if(sh_audio){        int i;        int len=0;	int skip_audio_bytes=0;	int curr_audio_pos=-1;	int audio_chunk_pos=-1;	int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;		if(sh_audio->audio.dwSampleSize){	    // constant rate audio stream#if 0	    int align;	    curr_audio_pos=(priv->avi_video_pts) * sh_audio->wf->nAvgBytesPerSec;	    if(curr_audio_pos<0)curr_audio_pos=0;	    align=sh_audio->audio.dwSampleSize;	    if(sh_audio->wf->nBlockAlign>align) align=sh_audio->wf->nBlockAlign;	    curr_audio_pos/=align;	    curr_audio_pos*=align;#else	    curr_audio_pos=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;	    curr_audio_pos-=sh_audio->audio.dwStart;	    curr_audio_pos*=sh_audio->audio.dwSampleSize;#endif        // find audio chunk pos:          for(i=0;i<chunk_max;i++){            int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;            if(avi_stream_id(id)==d_audio->id){                len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;                if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){                  break;                }                ++d_audio->pack_no;                priv->audio_block_no+=priv->audio_block_size ?		    ((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;                d_audio->dpos+=len;            }          }	  audio_chunk_pos=i;	  skip_audio_bytes=curr_audio_pos-d_audio->dpos;          mp_msg(MSGT_SEEK,MSGL_V,"SEEK: i=%d (max:%d) dpos=%d (wanted:%d)  \n",	      i,chunk_max,(int)d_audio->dpos,curr_audio_pos);	      	} else {	    // VBR audio	    int chunks=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;	    audio_chunk_pos=0;	            // find audio chunk pos:          for(i=0;i<priv->idx_size && chunks>0;i++){            int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;            if(avi_stream_id(id)==d_audio->id){                len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;		if(i>chunk_max){		  skip_audio_bytes+=len;		} else {		  ++d_audio->pack_no;                  priv->audio_block_no+=priv->audio_block_size ?		    ((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;                  d_audio->dpos+=len;		  audio_chunk_pos=i;		}//		--chunks;		if(priv->audio_block_size)		    chunks-=(len+priv->audio_block_size-1)/priv->audio_block_size;            }          }	  //if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max;	  //	  printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d  \n",//	      priv->avi_video_pts, audio_chunk_pos, );		}		// Now we have:	//      audio_chunk_pos = chunk no in index table (it's <=chunk_max)	//      skip_audio_bytes = bytes to be skipped after chunk seek	//      d-audio->pack_no = chunk_no in stream at audio_chunk_pos	//      d_audio->dpos = bytepos in stream at audio_chunk_pos	// let's seek!	          // update stream position:          d_audio->pos=audio_chunk_pos;//          d_audio->dpos=apos;//	  d_audio->pts=initial_pts_delay+(float)apos/(float)sh_audio->wf->nAvgBytesPerSec;		if(demuxer->type==DEMUXER_TYPE_AVI){	  // interleaved stream:	  if(audio_chunk_pos<video_chunk_pos){            // calc priv->skip_video_frames & adjust video pts counter:	    for(i=audio_chunk_pos;i<video_chunk_pos;i++){              int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;              if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;            }            // requires for correct audio pts calculation (demuxer):            priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;	    priv->avi_audio_pts=priv->avi_video_pts;	    // set index position:	    priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;	  }	} else {	    // non-interleaved stream:	    priv->idx_pos_a=audio_chunk_pos;	    priv->idx_pos_v=video_chunk_pos;	    priv->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;	}	          mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d  (a:%d v:%d)  v.skip=%d  a.skip=%d/%4.3f  \n",            (int)priv->idx_pos,audio_chunk_pos,video_chunk_pos,            (int)priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);          if(skip_audio_bytes){            demux_read_data(d_audio,NULL,skip_audio_bytes);            //d_audio->pts=0; // PTS is outdated because of the raw data skipping          }	  resync_audio_stream(sh_audio);//          sh_audio->timer=-skip_audio_secs;      }	d_video->pts=priv->avi_video_pts; // OSD}void demux_close_avi(demuxer_t *demuxer) {  avi_priv_t* priv=demuxer->priv;  if(!priv)    return;  if(priv->idx_size > 0)    free(priv->idx);  free(priv);}int demux_avi_control(demuxer_t *demuxer,int cmd, void *arg){    avi_priv_t *priv=demuxer->priv;/*    demux_stream_t *d_audio=demuxer->audio;*/    demux_stream_t *d_video=demuxer->video;/*    sh_audio_t *sh_audio=d_audio->sh;*/    sh_video_t *sh_video=d_video->sh;    switch(cmd) {	case DEMUXER_CTRL_GET_TIME_LENGTH:    	    if (!priv->numberofframes) return DEMUXER_CTRL_DONTKNOW;	    *((unsigned long *)arg)=priv->numberofframes/sh_video->fps;	    if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS;	    return DEMUXER_CTRL_OK;	case DEMUXER_CTRL_GET_PERCENT_POS:    	    if (!priv->numberofframes) {              return DEMUXER_CTRL_DONTKNOW;	    }	    *((int *)arg)=(int)(priv->video_pack_no*100/priv->numberofframes);	    if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS;	    return DEMUXER_CTRL_OK;	default:	    return DEMUXER_CTRL_NOTIMPL;    }}

⌨️ 快捷键说明

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