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

📄 demux_ogg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 4 页
字号:
	      ogg_d->pos -= pa;	      continue;	    }	    /// We need more data	    buf = ogg_sync_buffer(sync,BLOCK_SIZE);	    	    len = stream_read(s,buf,BLOCK_SIZE);	    if(len == 0 && s->eof) {	      mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");	      return 0;	    }	    ogg_sync_wrote(sync,len);	  } /// Page loop	  ogg_d->last_size = pa;	  /// Find the page's logical stream	  if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {	    mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");	    return 0;	  }	  /// Take the page	  if(ogg_stream_pagein(os,page) == 0)	    break;	  /// Page was invalid => retry	  mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");	  ogg_d->pos += ogg_d->last_size;	}      } else /// Packet was corrupted	mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);    } /// Packet loop        /// Is the actual logical stream in use ?    if(id == d->audio->id)      ds = d->audio;    else if(id == d->video->id)      ds = d->video;    else if (ogg_d->subs[id].text)      ds = d->sub;    if(ds) {      if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))	continue; /// Unuseful packet, get another      d->filepos = ogg_d->pos;      return 1;    }  } /// while(1)}/// For avi with Ogg audio stream we have to create an ogg demuxer for this// stream, then we join the avi and ogg demuxer with a demuxers demuxerdemuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {  demuxer_t  *od;  ogg_demuxer_t *ogg_d;  stream_t* s;  uint32_t hdrsizes[3];  demux_packet_t *dp;  sh_audio_t *sh_audio = demuxer->audio->sh;  int np;  unsigned char *p = NULL,*buf;  int plen;  /// Check that the cbSize is enouth big for the following reads  if(sh_audio->wf->cbSize < 22+3*sizeof(uint32_t)) {    mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");    goto fallback;  }  /// Get the size of the 3 header packet  memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+22+sizeof(WAVEFORMATEX), 3*sizeof(uint32_t));//  printf("\n!!!!!! hdr sizes: %d %d %d   \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);  /// Check the size  if(sh_audio->wf->cbSize < 22+3*sizeof(uint32_t)+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {    mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");    goto fallback;  }  // Build the ogg demuxer private datas  ogg_d = (ogg_demuxer_t*)calloc(1,sizeof(ogg_demuxer_t));  ogg_d->num_sub = 1;  ogg_d->subs = (ogg_stream_t*)malloc(sizeof(ogg_stream_t));  ogg_d->subs[0].vorbis = 1;   // Init the ogg physical stream  ogg_sync_init(&ogg_d->sync);  // Get the first page of the stream : we assume there only 1 logical stream  while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {    if(np < 0) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");      free(ogg_d);      goto fallback;    }    // Add some data    plen = ds_get_packet(demuxer->audio,&p);        buf = ogg_sync_buffer(&ogg_d->sync,plen);    memcpy(buf,p,plen);    ogg_sync_wrote(&ogg_d->sync,plen);  }  // Init the logical stream  mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));  ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));  // Write the page  ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);  // Create the ds_stream and the ogg demuxer  s = new_ds_stream(demuxer->audio);  od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2);  /// Add the header packets in the ogg demuxer audio stream  // Initial header  dp = new_demux_packet(hdrsizes[0]);  memcpy(dp->buffer,((unsigned char*)sh_audio->wf)+22+sizeof(WAVEFORMATEX)+3*sizeof(uint32_t),hdrsizes[0]);  ds_add_packet(od->audio,dp);  /// Comments  dp = new_demux_packet(hdrsizes[1]);  memcpy(dp->buffer,((unsigned char*)sh_audio->wf)+22+sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0],hdrsizes[1]);  ds_add_packet(od->audio,dp);  /// Code book  dp = new_demux_packet(hdrsizes[2]);  memcpy(dp->buffer,((unsigned char*)sh_audio->wf)+22+sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0]+hdrsizes[1],hdrsizes[2]);  ds_add_packet(od->audio,dp);  // Finish setting up the ogg demuxer  od->priv = ogg_d;  sh_audio = new_sh_audio(od,0);  od->audio->id = 0;  od->video->id = -2;  od->audio->sh = sh_audio;  sh_audio->ds = od->audio;  sh_audio->format = FOURCC_VORBIS;  /// Return the joined demuxers  return new_demuxers_demuxer(demuxer,od,demuxer); fallback:  demuxer->audio->id = -2;  return demuxer;}extern void resync_audio_stream(sh_audio_t *sh_audio);void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,int flags) {  ogg_demuxer_t* ogg_d = demuxer->priv;  ogg_sync_state* sync = &ogg_d->sync;  ogg_page* page= &ogg_d->page;  ogg_stream_state* oss;  ogg_stream_t* os;  demux_stream_t* ds;  sh_audio_t* sh_audio = demuxer->audio->sh;  ogg_packet op;  float rate;  int i,sp,first,precision=1,do_seek=1;  vorbis_info* vi = NULL;  int64_t gp = 0, old_gp;  void *context = NULL;  off_t pos, old_pos;  int np;  int is_gp_valid;  float pts;  int is_keyframe;  int samplesize=1;  if(demuxer->video->id >= 0) {    ds = demuxer->video;    /* demux_ogg_read_packet needs decoder context for Theora streams */    if (((sh_video_t*)demuxer->video->sh)->format == FOURCC_THEORA)      context = ((sh_video_t*)demuxer->video->sh)->context;    rate = ogg_d->subs[ds->id].samplerate;  } else {    ds = demuxer->audio;    /* demux_ogg_read_packet needs decoder context for Vorbis streams */    if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)      context = ((sh_audio_t*)demuxer->audio->sh)->context;    vi = &((ov_struct_t*)((sh_audio_t*)ds->sh)->context)->vi;    rate = (float)vi->rate;    samplesize = ((sh_audio_t*)ds->sh)->samplesize;  }  os = &ogg_d->subs[ds->id];  oss = &os->stream;  old_gp = os->lastpos;  old_pos = ogg_d->pos;  //calculate the granulepos to seek to    gp = flags & 1 ? 0 : os->lastpos;  if(flags & 2) {    if (ogg_d->final_granulepos > 0)      gp += ogg_d->final_granulepos * rel_seek_secs;      else      gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;  } else      gp += rel_seek_secs * rate;  if (gp < 0) gp = 0;  //calculate the filepos to seek to  if(ogg_d->syncpoints) {    for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {      if(ogg_d->syncpoints[sp].granulepos >= gp) break;    }    if(sp >= ogg_d->num_syncpoint) return;    if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)      sp--;    if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {      if (sp > 0 && gp < os->lastpos) sp--;      if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;    }    pos = ogg_d->syncpoints[sp].page_pos;    precision = 0;  } else {    pos = flags & 1 ? 0 : ogg_d->pos;    if(flags & 2)      pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;    else {      if (ogg_d->final_granulepos > 0) {        pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);      } else if (os->lastpos > 0) {      pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);    }  }    if (pos < 0) pos = 0;    if (pos > (demuxer->movi_end - demuxer->movi_start)) return;  } // if(ogg_d->syncpoints)  while(1) {    if (do_seek) {  stream_seek(demuxer->stream,pos+demuxer->movi_start);  ogg_sync_reset(sync);  for(i = 0 ; i < ogg_d->num_sub ; i++) {    ogg_stream_reset(&ogg_d->subs[i].stream);    ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;  }  ogg_d->pos = pos;  ogg_d->last_size = 0;      /* we just guess that we reached correct granulepos, in case a         subsequent search occurs before we read a valid granulepos */      os->lastpos = gp;      first = !(ogg_d->syncpoints);      do_seek=0;    }    ogg_d->pos += ogg_d->last_size;    ogg_d->last_size = 0;    np = ogg_sync_pageseek(sync,page);    if(np < 0)      ogg_d->pos -= np;    if(np <= 0) { // We need more data      char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);      int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);       if(len == 0 && demuxer->stream->eof) {	mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to seek !!!!\n");	break;      }      ogg_sync_wrote(sync,len);      continue;    }    ogg_d->last_size = np;    if(ogg_page_serialno(page) != oss->serialno)      continue;    if(ogg_stream_pagein(oss,page) != 0)      continue;     while(1) {      np = ogg_stream_packetout(oss,&op);      if(np < 0)	continue;      else if(np == 0)	break;      if (first) { /* Discard the first packet as it's probably broken,           and we don't have any other means to decide whether it is           complete or not. */        first = 0;        break;      }      is_gp_valid = (op.granulepos >= 0);      demux_ogg_read_packet(os,&op,context,&pts,&is_keyframe,samplesize);      if (precision && is_gp_valid) {        precision--;        if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {          //prepare another seek because we are off by more than 1s          pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);          if (pos < 0) pos = 0;          if (pos < (demuxer->movi_end - demuxer->movi_start)) {            do_seek=1;            break;          }        }      }      if (is_gp_valid && (pos > 0) && (old_gp > gp)          && (2 * (old_gp - op.granulepos) < old_gp - gp)) {        /* prepare another seek because looking for a syncpoint           destroyed the backward search */        pos = old_pos - 1.5 * (old_pos - pos);        if (pos < 0) pos = 0;        if (pos < (demuxer->movi_end - demuxer->movi_start)) {          do_seek=1;          break;        }      }      if(!precision && (is_keyframe || os->vorbis) ) {        ogg_sub.lines = 0;        vo_sub = &ogg_sub;        vo_osd_changed(OSDTYPE_SUBTITLE);        clear_sub = -1;	demux_ogg_add_packet(ds,os,ds->id,&op);	if(sh_audio)	  resync_audio_stream(sh_audio); 	return;      }     }  }  mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");  }void demux_close_ogg(demuxer_t* demuxer) {  ogg_demuxer_t* ogg_d = demuxer->priv;  int i;  if(!ogg_d)    return;#ifdef USE_ICONV  subcp_close();#endif  ogg_sync_clear(&ogg_d->sync);  if(ogg_d->subs)  {    for (i = 0; i < ogg_d->num_sub; i++)      ogg_stream_clear(&ogg_d->subs[i].stream);    free(ogg_d->subs);  }  if(ogg_d->syncpoints)    free(ogg_d->syncpoints);  if (ogg_d->text_ids)    free(ogg_d->text_ids);  if (ogg_d->text_langs) {    for (i = 0; i < ogg_d->n_text; i++)      if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);    free(ogg_d->text_langs);  }  free(ogg_d);}int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){  ogg_demuxer_t* ogg_d = demuxer->priv;  ogg_stream_t* os;  float rate;  if(demuxer->video->id >= 0) {    os = &ogg_d->subs[demuxer->video->id];    rate = os->samplerate;  } else {    os = &ogg_d->subs[demuxer->audio->id];    rate = (float)((ov_struct_t*)((sh_audio_t*)demuxer->audio->sh)->context)->vi.rate;  }    switch(cmd) {	case DEMUXER_CTRL_GET_TIME_LENGTH:	    if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;	    *((unsigned long *)arg)=ogg_d->final_granulepos / rate;	    return DEMUXER_CTRL_GUESS;	case DEMUXER_CTRL_GET_PERCENT_POS:	    if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;	    *((int *)arg)=(int)( (os->lastpos*100) / ogg_d->final_granulepos);	    return DEMUXER_CTRL_OK;	default:	    return DEMUXER_CTRL_NOTIMPL;    }}#endif

⌨️ 快捷键说明

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