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

📄 demux_ogg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 4 页
字号:
     }#endif /* HAVE_OGGTHEORA */# ifdef HAVE_FLAC  } else if (os->flac) {     /* we pass complete packets to flac, mustn't strip the header! */     data = pack->packet;#endif /* HAVE_FLAC */  } else {    if(*pack->packet & PACKET_TYPE_HEADER)      os->hdr_packets++;    else {    // Find data start    int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;    hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;    data = pack->packet + 1 + hdrlen;    // Calculate the timestamp    if(pack->granulepos == -1)      pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);    // If we alredy have a timestamp it can be a syncpoint    if(*pack->packet & PACKET_IS_SYNCPOINT)      *flags = 1;    *pts =  pack->granulepos/os->samplerate;    // Save the packet length and timestamp    os->lastsize = 0;    while(hdrlen) {      os->lastsize <<= 8;      os->lastsize |= pack->packet[hdrlen];      hdrlen--;    }    os->lastpos = pack->granulepos;  }  }  return data;}// check if clang has substring from comma separated langliststatic int demux_ogg_check_lang(char *clang, char *langlist){  char *c;  if (!langlist || !*langlist)    return 0;  while ((c = strchr(langlist, ',')))  {    if (!strncasecmp(clang, langlist, c - langlist))      return 1;    langlist = &c[1];  }  if (!strncasecmp(clang, langlist, strlen(langlist)))    return 1;  return 0;}static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id);/// Try to print out comments and also check for LANGUAGE= tagstatic void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc){  char *hdr, *val;  char **cmt = vc->user_comments;  int index;  ogg_demuxer_t *ogg_d = (ogg_demuxer_t *)d->priv;  while(*cmt)  {    hdr = NULL;    if (!strncasecmp(*cmt, "ENCODED_USING=", 14))    {      hdr = "Software";      val = *cmt + 14;    }    else if (!strncasecmp(*cmt, "LANGUAGE=", 9))    {      val = *cmt + 9;      if (identify)      {        if (ogg_d->subs[id].text)          mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);        else if (id != d->video->id)          mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);      }      if (ogg_d->subs[id].text)        mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);      // copy this language name into the array      index = demux_ogg_sub_reverse_id(d, id);      if (index >= 0) {	// in case of malicious files with more than one lang per track:	if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);	ogg_d->text_langs[index] = strdup(val);      }      // check for -slang if subs are uninitialized yet      if (os->text && d->sub->id == -1 && demux_ogg_check_lang(val, dvdsub_lang))      {	d->sub->id = id;	dvdsub_id = index;        mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);      }      else	hdr = "Language";    }    else if (!strncasecmp(*cmt, "ENCODER_URL=", 12))    {      hdr = "Encoder URL";      val = *cmt + 12;    }    else if (!strncasecmp(*cmt, "TITLE=", 6))    {      hdr = "Name";      val = *cmt + 6;    }    if (hdr)      mp_msg(MSGT_DEMUX, MSGL_V, " %s: %s\n", hdr, val);    cmt++;  }}/// Calculate the timestamp and add the packet to the demux stream// return 1 if the packet was added, 0 otherwisestatic int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {  demuxer_t* d = ds->demuxer;  demux_packet_t* dp;  unsigned char* data;  float pts = 0;  int flags = 0;  void *context = NULL;  int samplesize = 1;  // If packet is an comment header then we try to get comments at first  if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))  {    vorbis_info vi;    vorbis_comment vc;    vorbis_info_init(&vi);    vorbis_comment_init(&vc);    vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()    if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors      demux_ogg_check_comments(d, os, id, &vc);    vorbis_comment_clear(&vc);    vorbis_info_clear(&vi);  }  if (os->text) {    if (id == d->sub->id) // don't want to add subtitles to the demuxer for now      demux_ogg_add_sub(os,pack);    return 0;  }  // If packet is an header we jump it except for vorbis and theora  // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)  // We jump nothing for FLAC. Ain't this great? Packet contents have to be  // handled differently for each and every stream type. The joy! The joy!  if(!os->flac && ((*pack->packet & PACKET_TYPE_HEADER) &&      (ds != d->audio || ( ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) ) &&     (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA))))    return 0;  // For vorbis packet the packet is the data, for other codec we must jump  // the header  if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {     context = ((sh_audio_t *)ds->sh)->context;     samplesize = ((sh_audio_t *)ds->sh)->samplesize;  }  if (ds == d->video && ((sh_audio_t*)ds->sh)->format == FOURCC_THEORA)     context = ((sh_video_t *)ds->sh)->context;  data = demux_ogg_read_packet(os,pack,context,&pts,&flags,samplesize);  if(d->video->id < 0)      ((sh_audio_t*)ds->sh)->delay = pts;  /// Clear subtitles if necessary (for broken files)  if ((clear_sub > 0) && (pts >= clear_sub)) {    ogg_sub.lines = 0;    vo_sub = &ogg_sub;    vo_osd_changed(OSDTYPE_SUBTITLE);    clear_sub = -1;  }  /// Send the packet  dp = new_demux_packet(pack->bytes-(data-pack->packet));  memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));  dp->pts = pts;  dp->flags = flags;  ds_add_packet(ds,dp);  mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p  ds=%p  pts=%5.3f  len=%d  flag=%d  \n",      dp, ds, pts, dp->len, flags);  return 1;}/// if -forceidx build a table of all syncpoints to make seeking easier/// otherwise try to get at least the final_granuleposvoid demux_ogg_scan_stream(demuxer_t* demuxer) {  ogg_demuxer_t* ogg_d = demuxer->priv;  stream_t *s = demuxer->stream;  ogg_sync_state* sync = &ogg_d->sync;  ogg_page* page= &ogg_d->page;  ogg_stream_state* oss;  ogg_stream_t* os;  ogg_packet op;  int np,sid,p,samplesize=1;  void *context = NULL;  off_t pos, last_pos;  pos = last_pos = demuxer->movi_start;  // Reset the stream  if(index_mode == 2) {  stream_seek(s,demuxer->movi_start);  } else {    //the 270000 are just a wild guess    stream_seek(s,max(ogg_d->pos,demuxer->movi_end-270000));  }  ogg_sync_reset(sync);  // Get the serial number of the stream we use  if(demuxer->video->id >= 0) {    sid = demuxer->video->id;    /* 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;  }  else {    sid = demuxer->audio->id;    /* 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;      samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;    }  }  os = &ogg_d->subs[sid];  oss = &os->stream;  while(1) {    np = ogg_sync_pageseek(sync,page);    if(np < 0) { // We had to skip some bytes      if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);      pos += -np;      continue;    }    if(np <= 0) { // We need more data      char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);      int len = stream_read(s,buf,BLOCK_SIZE);      if(len == 0 && s->eof)	break;      ogg_sync_wrote(sync,len);      continue;    }    // The page is ready    //ogg_sync_pageout(sync,page);    if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want      pos += np;      continue;    }    if(ogg_stream_pagein(oss,page) != 0) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");      pos += np;      continue;    }    p = 0;    while(ogg_stream_packetout(oss,&op) == 1) {      float pts;      int flags;      demux_ogg_read_packet(os,&op,context,&pts,&flags,samplesize);      if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;      if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {	ogg_d->syncpoints = (ogg_syncpoint_t*)realloc(ogg_d->syncpoints,(ogg_d->num_syncpoint+1)*sizeof(ogg_syncpoint_t));	ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;	ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;	ogg_d->num_syncpoint++;      }      p++;    }    if(p > 1 || (p == 1 && ! ogg_page_continued(page)))      last_pos = pos;    pos += np;    if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));  }  if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");  if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);  mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %lld\n",ogg_d->final_granulepos);  stream_reset(s);  stream_seek(s,demuxer->movi_start);  ogg_sync_reset(sync);  for(np = 0 ; np < ogg_d->num_sub ; np++) {    ogg_stream_reset(&ogg_d->subs[np].stream);    ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;  }    // Get the first page  while(1) {    np = ogg_sync_pageout(sync,page);    if(np <= 0) { // We need more data      char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);      int len = stream_read(s,buf,BLOCK_SIZE);      if(len == 0 && s->eof) {	mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");	break;      }            ogg_sync_wrote(sync,len);      continue;    }    demux_ogg_get_page_stream(ogg_d,&oss);    ogg_stream_pagein(oss,page);    break;  }  }extern void print_wave_header(WAVEFORMATEX *h);extern void print_video_header(BITMAPINFOHEADER *h);/** \brief Return the number of subtitle tracks in the file.  \param demuxer The demuxer for which the number of subtitle tracks  should be returned.*/int demux_ogg_num_subs(demuxer_t *demuxer) {  ogg_demuxer_t *ogg_d = (ogg_demuxer_t *)demuxer->priv;  return ogg_d->n_text;}/** \brief Change the current subtitle stream and return its ID.  \param demuxer The demuxer whose subtitle stream will be changed.  \param new_num The number of the new subtitle track. The number must be  between 0 and ogg_d->n_text - 1.  \returns The Ogg stream number ( = page serial number) of the newly selected  track.*/int demux_ogg_sub_id(demuxer_t *demuxer, int index) {  ogg_demuxer_t *ogg_d = (ogg_demuxer_t *)demuxer->priv;  return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];}/** \brief Translate the ogg track number into the subtitle number. *  \param demuxer The demuxer about whose subtitles we are inquiring. *  \param id The ogg track number of the subtitle track. */static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {  ogg_demuxer_t *ogg_d = (ogg_demuxer_t *)demuxer->priv;  int i;  for (i = 0; i < ogg_d->n_text; i++)    if (ogg_d->text_ids[i] == id) return i;  return -1;}/** \brief Lookup the subtitle language by the subtitle number.  Returns NULL on out-of-bounds input. *  \param demuxer The demuxer about whose subtitles we are inquiring. *  \param index The subtitle number. */char *demux_ogg_sub_lang(demuxer_t *demuxer, int index) {  ogg_demuxer_t *ogg_d = (ogg_demuxer_t *)demuxer->priv;  return (index < 0) ? NULL : (index >= ogg_d->n_text) ? NULL : ogg_d->text_langs[index];}void demux_close_ogg(demuxer_t* demuxer);/// Open an ogg physical streamint demux_ogg_open(demuxer_t* demuxer) {  ogg_demuxer_t* ogg_d;  stream_t *s;  char* buf;  int np,s_no, n_audio = 0, n_video = 0;  int audio_id = -1, video_id = -1, text_id = -1;  ogg_sync_state* sync;  ogg_page* page;  ogg_packet pack;  sh_audio_t* sh_a;  sh_video_t* sh_v;#ifdef USE_ICONV  subcp_open(NULL);#endif  clear_sub = -1;  s = demuxer->stream;  ogg_d = (ogg_demuxer_t*)calloc(1,sizeof(ogg_demuxer_t));  sync = &ogg_d->sync;  page = &ogg_d->page;

⌨️ 快捷键说明

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