demux_ogg.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,617 行 · 第 1/4 页

C
1,617
字号
      break;    }    /// Init  the data structure needed for a logical stream    ogg_d->subs = (ogg_stream_t*)realloc(ogg_d->subs,(ogg_d->num_sub+1)*sizeof(ogg_stream_t));    memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));    /// Get the stream serial number    s_no = ogg_page_serialno(page);    ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);    mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);    // Take the first page    ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);    // Get first packet of the page    ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);    // Reset our vars    sh_a = NULL;    sh_v = NULL;    ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;    // Check for Vorbis    if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {      sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);      sh_a->format = FOURCC_VORBIS;      ogg_d->subs[ogg_d->num_sub].vorbis = 1;      ogg_d->subs[ogg_d->num_sub].id = n_audio;      n_audio++;      mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);    } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {      sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);      sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);      sh_a->format = FOURCC_SPEEX;      sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint32(&pack.packet[36]);      sh_a->channels = sh_a->wf->nChannels = get_uint32(&pack.packet[48]);      sh_a->wf->wFormatTag = sh_a->format;      sh_a->wf->nAvgBytesPerSec = get_uint32(&pack.packet[52]);      sh_a->wf->nBlockAlign = 0;      sh_a->wf->wBitsPerSample = 16;      sh_a->samplesize = 2;      sh_a->wf->cbSize = pack.bytes;      memcpy(&sh_a->wf[1], pack.packet, pack.bytes);      ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;      ogg_d->subs[ogg_d->num_sub].speex = 1;      ogg_d->subs[ogg_d->num_sub].id = n_audio;      n_audio++;      mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);      // check for Theora#   ifdef HAVE_OGGTHEORA    } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {	int errorCode = 0;	theora_info inf;	theora_comment cc;		theora_info_init (&inf);	theora_comment_init (&cc);		errorCode = theora_decode_header (&inf, &cc, &pack);	if (errorCode)	    mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",		   errorCode);	else	{	    sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);	    sh_v->context = NULL;	    sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));	    sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);	    sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;	    sh_v->fps = ((double)inf.fps_numerator)/		(double)inf.fps_denominator;	    sh_v->frametime = ((double)inf.fps_denominator)/		(double)inf.fps_numerator;	    sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;	    sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;	    sh_v->bih->biBitCount = 24;	    sh_v->bih->biPlanes = 3;	    sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) * 				      sh_v->bih->biWidth*sh_v->bih->biHeight);	    ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;	    ogg_d->subs[ogg_d->num_sub].theora = 1;	    ogg_d->subs[ogg_d->num_sub].id = n_video;	    n_video++;	    mp_msg(MSGT_DEMUX,MSGL_INFO,		   "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",		   ogg_d->num_sub,		   (int)inf.version_major, 		   (int)inf.version_minor, 		   (int)inf.version_subminor, 		   n_video - 1);	    if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);	}	theora_comment_clear(&cc);	theora_info_clear(&inf);#   endif /* HAVE_OGGTHEORA */    } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {	sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);	sh_a->format =  mmioFOURCC('f', 'L', 'a', 'C');	ogg_d->subs[ogg_d->num_sub].id = n_audio;	n_audio++;	ogg_d->subs[ogg_d->num_sub].flac = 1;	sh_a->wf = NULL;	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);    } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {	sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);	sh_a->format =  mmioFOURCC('f', 'L', 'a', 'C');	ogg_d->subs[ogg_d->num_sub].id = n_audio;	n_audio++;	ogg_d->subs[ogg_d->num_sub].flac = 2;	sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);	sh_a->wf->wFormatTag = sh_a->format;	sh_a->wf->cbSize = 34;	memcpy(&sh_a->wf[1], &pack.packet[17], 34);	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);      /// Check for old header    } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {       // Old video header      if(get_uint32 (pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {	sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);	sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));	sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);	sh_v->bih->biCompression=	sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],				pack.packet[70],pack.packet[71]);	sh_v->frametime = get_uint64(pack.packet+164)*0.0000001;	sh_v->fps = 1/sh_v->frametime;	sh_v->disp_w = sh_v->bih->biWidth = get_uint32(pack.packet+176);	sh_v->disp_h = sh_v->bih->biHeight = get_uint32(pack.packet+180);	sh_v->bih->biBitCount = get_uint16(pack.packet+182);	if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME	sh_v->bih->biPlanes=1;	sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;	ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;	ogg_d->subs[ogg_d->num_sub].id = n_video;	n_video++;	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",	       ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);	if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);	// Old audio header      } else if(get_uint32(pack.packet+96) == 0x05589F81) {	unsigned int extra_size;	sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);	extra_size = get_uint16(pack.packet+140);	sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);	sh_a->format = sh_a->wf->wFormatTag = get_uint16(pack.packet+124);	sh_a->channels = sh_a->wf->nChannels = get_uint16(pack.packet+126);	sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint32(pack.packet+128);	sh_a->wf->nAvgBytesPerSec = get_uint32(pack.packet+132);	sh_a->wf->nBlockAlign = get_uint16(pack.packet+136);	sh_a->wf->wBitsPerSample = get_uint16(pack.packet+138);	sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;	sh_a->wf->cbSize = extra_size;	if(extra_size > 0)	  memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);	ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;	ogg_d->subs[ogg_d->num_sub].id = n_audio;	n_audio++;	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1);	if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);      } else	mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);        // Check new header    } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER && 	      pack.bytes >= (int)sizeof(stream_header)+1) {      stream_header *st = (stream_header*)(pack.packet+1);      /// New video header      if(strncmp(st->streamtype,"video",5) == 0) {	sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);	sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));	sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);	sh_v->bih->biCompression=	sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],				  st->subtype[2],st->subtype[3]);	sh_v->frametime = get_uint64(&st->time_unit)*0.0000001;	sh_v->fps = 1.0/sh_v->frametime;	sh_v->bih->biBitCount = get_uint16(&st->bits_per_sample);	sh_v->disp_w = sh_v->bih->biWidth = get_uint32(&st->sh.video.width);	sh_v->disp_h = sh_v->bih->biHeight = get_uint32(&st->sh.video.height);	if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME	sh_v->bih->biPlanes=1;	sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;	ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;	ogg_d->subs[ogg_d->num_sub].id = n_video;	n_video++;	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",	       ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);	if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);	/// New audio header      } else if(strncmp(st->streamtype,"audio",5) == 0) {	char buffer[5];	unsigned int extra_size = get_uint32 (&st->size) - sizeof(stream_header);	unsigned int extra_offset = 0;	memcpy(buffer,st->subtype,4);	buffer[4] = '\0';        /* Nasty workaround. stream_header.size seems not to contain the real           size in all cases. There are four extra bytes that are unaccounted           for in front of the real codec initialization data _at least_ for           AAC. So far I've only seen those bytes being all 0, so we can           just skip them here. */	if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {	  extra_size -= 4;	  extra_offset = 4;	}	sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);	sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);	sh_a->format =  sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);	sh_a->channels = sh_a->wf->nChannels = get_uint16(&st->sh.audio.channels);	sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint64(&st->samples_per_unit);	sh_a->wf->nAvgBytesPerSec = get_uint32(&st->sh.audio.avgbytespersec);	sh_a->wf->nBlockAlign = get_uint16(&st->sh.audio.blockalign);	sh_a->wf->wBitsPerSample = get_uint16(&st->bits_per_sample);	sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;	sh_a->wf->cbSize = extra_size;	if(extra_size)	  memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);	ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;	ogg_d->subs[ogg_d->num_sub].id = n_audio;	n_audio++;	mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1);	if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);	/// Check for text (subtitles) header      } else if (strncmp(st->streamtype, "text", 4) == 0) {          mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n", ogg_d->num_sub, ogg_d->n_text);	  ogg_d->subs[ogg_d->num_sub].samplerate= get_uint64(&st->time_unit)/10;	  ogg_d->subs[ogg_d->num_sub].text = 1;          ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;          if (demuxer->sub->id == ogg_d->n_text)            text_id = ogg_d->num_sub;          new_sh_sub(demuxer, ogg_d->n_text);          ogg_d->n_text++;          ogg_d->text_ids = (int *)realloc(ogg_d->text_ids, sizeof(int) * ogg_d->n_text);          ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;          ogg_d->text_langs = (char **)realloc(ogg_d->text_langs, sizeof(char *) * ogg_d->n_text);          ogg_d->text_langs[ogg_d->n_text - 1] = NULL;	//// Unknown header type      } else	mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);      /// Unknown (invalid ?) header    } else      mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);    if(sh_a || sh_v) {      demux_stream_t* ds = NULL;      if(sh_a) {	// If the audio stream is not defined we took the first one	if(demuxer->audio->id == -1) {	  demuxer->audio->id = n_audio - 1;//	  if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);	}	/// Is it the stream we want	if(demuxer->audio->id == (n_audio - 1)) {	  demuxer->audio->sh = sh_a;	  sh_a->ds = demuxer->audio;	  ds = demuxer->audio;          audio_id = ogg_d->num_sub;	}      }      if(sh_v) {	/// Also for video	if(demuxer->video->id == -1) {	  demuxer->video->id = n_video - 1;//	  if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);	}	if(demuxer->video->id == (n_video - 1)) {	  demuxer->video->sh = sh_v;	  sh_v->ds = demuxer->video;	  ds = demuxer->video;          video_id = ogg_d->num_sub;	}      }      /// Add the header packets if the stream isn't seekable      if(ds && !s->end_pos) {	/// Finish the page, otherwise packets will be lost	do {	  demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);	} while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);      }    }    ogg_d->num_sub++;        }  if(!n_video && !n_audio) {    goto err_out;  }  if(!n_video || (video_id < 0))    demuxer->video->id = -2;  else    demuxer->video->id = video_id;  if(!n_audio || (audio_id < 0))    demuxer->audio->id = -2;  else    demuxer->audio->id = audio_id;  /* Disable the subs only if there are no text streams at all.     Otherwise the stream to display might be chosen later when the comment     packet is encountered and the user used -slang instead of -sid. */  if(!ogg_d->n_text)    demuxer->sub->id = -2;  else if (text_id >= 0) {    demuxer->sub->id = text_id;    mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);  }  ogg_d->final_granulepos=0;  if(!s->end_pos)    demuxer->seekable = 0;  else {    demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)    demuxer->movi_end = s->end_pos;    demuxer->seekable = 1;    demux_ogg_scan_stream(demuxer);  }  mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":"");  sh_a = demuxer->audio->sh;  if(sh_a)    if(sh_a->format == FOURCC_VORBIS)      fixup_vorbis_wf(sh_a, ogg_d);  return DEMUXER_TYPE_OGG;err_out:  return 0;}static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {  ogg_demuxer_t* ogg_d;  stream_t *s;  demux_stream_t *ds;  ogg_sync_state* sync;  ogg_stream_state* os;  ogg_page* page;  ogg_packet pack;  int np = 0, id=0;  s = d->stream;  ogg_d = d->priv;  sync = &ogg_d->sync;  page = &ogg_d->page;  /// Find the stream we are working on  if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");      return 0;  }  while(1) {    np = 0;    ds = NULL;    /// Try to get some packet from the current page    while( (np = ogg_stream_packetout(os,&pack)) != 1) {      /// No packet we go the next page      if(np == 0) {	while(1) {	  int pa,len;	  char *buf;	  ogg_d->pos += ogg_d->last_size;	  /// Get the next page from the physical stream	  while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {	    /// Error : we skip some bytes	    if(pa < 0) {	      mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");	      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

⌨️ 快捷键说明

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