changeset 5133:9841a86d66f9

Initial ogg demuxer. No seeking, a/v sync is broken. Support avi with ogg/vorbis audio.
author albeu
date Sat, 16 Mar 2002 14:32:03 +0000
parents cfccb5dbe992
children 83b3dc5132a5
files dec_audio.c libmpdemux/Makefile libmpdemux/demux_ogg.c libmpdemux/demuxer.c libmpdemux/demuxer.h libmpdemux/stream.c libmpdemux/stream.h
diffstat 7 files changed, 731 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/dec_audio.c	Sat Mar 16 06:01:13 2002 +0000
+++ b/dec_audio.c	Sat Mar 16 14:32:03 2002 +0000
@@ -73,13 +73,8 @@
 #include <math.h>
 #include <vorbis/codec.h>
 
+// This struct is also defined in demux_ogg.c => common header ?
 typedef struct ov_struct_st {
-  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
-  ogg_stream_state os; /* take physical pages, weld into a logical
-			  stream of packets */
-  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
-  ogg_packet       op; /* one raw packet of data for decode */
-
   vorbis_info      vi; /* struct that stores all the static vorbis bitstream
 			  settings */
   vorbis_comment   vc; /* struct that stores all the bitstream user comments */
@@ -389,6 +384,7 @@
   driver=0;
 #else
   /* OggVorbis audio via libvorbis, compatible with files created by nandub and zorannt codec */
+  // Is there always 1024 samples/frame ? ***** Albeu
   sh_audio->audio_out_minsize=1024*4; // 1024 samples/frame
 #endif
   break;
@@ -759,124 +755,61 @@
 }
 #ifdef HAVE_OGGVORBIS
 case AFM_VORBIS: {
-  // OggVorbis Audio:
-#if 0 /* just here for reference - atmos */ 
-  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
-  ogg_stream_state os; /* take physical pages, weld into a logical
-			  stream of packets */
-  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
-  ogg_packet       op; /* one raw packet of data for decode */
-  
-  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
-			  settings */
-  vorbis_comment   vc; /* struct that stores all the bitstream user comments */
-  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
-  vorbis_block     vb; /* local working space for packet->PCM decode */
-#else
-  /* nix, nada, rien, nothing, nem, nüx */
-#endif
-
-  uint32_t hdrsizes[3];/* stores vorbis header sizes from AVI audio header,
-			  maybe use ogg_uint32_t */
-  //int i;
-  int ret;
-  char *buffer;
-  ogg_packet hdr;
-  //ov_struct_t *s=&sh_audio->ov;
-  sh_audio->ov=malloc(sizeof(ov_struct_t));
-  //s=&sh_audio->ov;
-
-  vorbis_info_init(&sh_audio->ov->vi);
-  vorbis_comment_init(&sh_audio->ov->vc);
+  ogg_packet op;
+  vorbis_comment vc;
+  struct ov_struct_st *ov;
 
-  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OggVorbis: cbsize: %i\n", sh_audio->wf->cbSize);
-  memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX), 3*sizeof(uint32_t));
-  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"OggVorbis: Read header sizes: initial: %i comment: %i codebook: %i\n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
-  /*for(i=12; i <= 40; i+=2) { // header bruteforce :)
-    memcpy(hdrsizes, ((unsigned char*)sh_audio->wf)+i, 3*sizeof(uint32_t));
-    printf("OggVorbis: Read header sizes (%i): %ld %ld %ld\n", i, hdrsizes[0], hdrsizes[1], hdrsizes[2]);
-  }*/
-
-  /* read headers */ // FIXME disable sound on errors here, we absolutely need this headers! - atmos
-  hdr.packet=NULL;
-  hdr.b_o_s  = 1; /* beginning of stream for first packet */  
-  hdr.bytes  = hdrsizes[0];
-  hdr.packet = realloc(hdr.packet,hdr.bytes);
-  memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t),hdr.bytes);
-  if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
-    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: initial (identification) header broken!\n");
-  hdr.b_o_s  = 0;
-  hdr.bytes  = hdrsizes[1];
-  hdr.packet = realloc(hdr.packet,hdr.bytes);
-  memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0],hdr.bytes);
-  if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
-    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: comment header broken!\n");
-  hdr.bytes  = hdrsizes[2];
-  hdr.packet = realloc(hdr.packet,hdr.bytes);
-  memcpy(hdr.packet,((unsigned char*)sh_audio->wf)+2*sizeof(WAVEFORMATEX)+3*sizeof(uint32_t)+hdrsizes[0]+hdrsizes[1],hdr.bytes);
-  if(vorbis_synthesis_headerin(&sh_audio->ov->vi,&sh_audio->ov->vc,&hdr)<0)
+  /// Init the decoder with the 3 header packets
+  ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st));
+  vorbis_info_init(&ov->vi);
+  vorbis_comment_init(&vc);
+  op.bytes = ds_get_packet(sh_audio->ds,&op.packet);
+  op.b_o_s  = 1;
+  /// Header
+  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
+    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n");
+    driver = 0;
+    free(ov);
+    break;
+  }
+  op.bytes = ds_get_packet(sh_audio->ds,&op.packet);
+  op.b_o_s  = 0;
+  /// Comments
+  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
+    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n");
+    driver = 0;
+    free(ov);
+    break;
+  }
+  op.bytes = ds_get_packet(sh_audio->ds,&op.packet);
+  //// Codebook
+  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) {
     mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n");
-  hdr.bytes=0;
-  hdr.packet = realloc(hdr.packet,hdr.bytes); /* free */
-  /* done with the headers */
-
-
-  /* Throw the comments plus a few lines about the bitstream we're
-     decoding */
-  {
-    char **ptr=sh_audio->ov->vc.user_comments;
+    driver = 0;
+    free(ov);
+    break;
+  } else { /// Print the infos
+    char **ptr=vc.user_comments;
     while(*ptr){
       mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
       ++ptr;
     }
-      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel, %ldHz, %ldkbit/s %cBR\n",sh_audio->ov->vi.channels,sh_audio->ov->vi.rate,sh_audio->ov->vi.bitrate_nominal/1000, (sh_audio->ov->vi.bitrate_lower!=sh_audio->ov->vi.bitrate_nominal)||(sh_audio->ov->vi.bitrate_upper!=sh_audio->ov->vi.bitrate_nominal)?'V':'C');
-      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",sh_audio->ov->vc.vendor);
+    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel, %ldHz, %ldkbit/s %cBR\n",ov->vi.channels,ov->vi.rate,ov->vi.bitrate_nominal/1000, (ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C');
+    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
   }
-  sh_audio->channels=sh_audio->ov->vi.channels; 
-  sh_audio->samplerate=sh_audio->ov->vi.rate;
-  sh_audio->i_bps=sh_audio->ov->vi.bitrate_nominal/8;
-    
-//  printf("[\n");
-//  sh_audio->a_buffer_len=sh_audio->audio_out_minsize;///ov->vi.channels;
-//  printf("]\n");
-
-  /* OK, got and parsed all three headers. Initialize the Vorbis
-     packet->PCM decoder. */
-  vorbis_synthesis_init(&sh_audio->ov->vd,&sh_audio->ov->vi); /* central decode state */
-  vorbis_block_init(&sh_audio->ov->vd,&sh_audio->ov->vb);     /* local state for most of the decode
-								 so multiple block decodes can
-								 proceed in parallel.  We could init
-								 multiple vorbis_block structures
-								 for vd here */
-  //printf("OggVorbis: synthesis and block init done.\n"); 
-  ogg_sync_init(&sh_audio->ov->oy); /* Now we can read pages */
 
-  while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) {
-    if(ret == -1)
-      mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: Pageout: not properly synced, had to skip some bytes.\n");
-    else
-    if(ret == 0) {
-      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: need more data to verify page, reading more data.\n");
-      /* submit a a_buffer_len  block to libvorbis' Ogg layer */
-      buffer=ogg_sync_buffer(&sh_audio->ov->oy,256);
-      ogg_sync_wrote(&sh_audio->ov->oy,demux_read_data(sh_audio->ds,buffer,256));
-    }
-  }
-  mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: successfull.\n");
-  ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og); /* we can ignore any errors here
-  					 as they'll also become apparent
-  					 at packetout */
+  // Setup the decoder
+  sh_audio->channels=ov->vi.channels; 
+  sh_audio->samplerate=ov->vi.rate;
+  sh_audio->i_bps=ov->vi.bitrate_nominal/8;
+  sh_audio->context = ov;
 
-  /* Get the serial number and set up the rest of decode. */
-  /* serialno first; use it to set up a logical stream */
-  ogg_stream_init(&sh_audio->ov->os,ogg_page_serialno(&sh_audio->ov->og));
-  
+  /// Finish the decoder init
+  vorbis_synthesis_init(&ov->vd,&ov->vi);
+  vorbis_block_init(&ov->vd,&ov->vb);
   mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n");
-
-  break;
-}
+} break;
 #endif
-
 #ifdef USE_LIBMAD
  case AFM_MAD:
    {
@@ -982,117 +915,64 @@
 //        len=MP3_DecodeFrame(buf,3);
         break;
 #ifdef HAVE_OGGVORBIS
-      case AFM_VORBIS: { // OggVorbis
-        /* note: good minlen would be 4k or 8k IMHO - atmos */
-        int ret;
-        char *buffer;
-        int bytes;
-	int samples;
-	float **pcm;
-        //ogg_int16_t convbuffer[4096];
-//        int convsize;
-        int readlen=1024;
-        len=0;
-//        convsize=minlen/sh_audio->ov->vi.channels;
-
-        while(len < minlen) { /* double loop allows for break in inner loop */
-        while(len < minlen) { /* without aborting the outer loop - atmos    */
-        ret=ogg_stream_packetout(&sh_audio->ov->os,&sh_audio->ov->op);
-        if(ret==0) {
-	  int xxx=0;
-          //printf("OggVorbis: Packetout: need more data, paging!\n");
-          while((ret = ogg_sync_pageout(&sh_audio->ov->oy,&sh_audio->ov->og))!=1) {
-            if(ret == -1)
-              mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pageout: not properly synced, had to skip some bytes.\n");
-            else
-            if(ret == 0) {
-              //printf("OggVorbis: Pageout: need more data to verify page, reading more data.\n");
-              /* submit a readlen k block to libvorbis' Ogg layer */
-              buffer=ogg_sync_buffer(&sh_audio->ov->oy,readlen);
-              bytes=demux_read_data(sh_audio->ds,buffer,readlen);
-	      xxx+=bytes;
-              ogg_sync_wrote(&sh_audio->ov->oy,bytes);
-              if(bytes==0)
-                mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: 0Bytes written, possible End of Stream\n");
-            }
-          }
-	  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[sync: %d ]\n",xxx);
-          //printf("OggVorbis: Pageout: successfull, pagin in.\n");
-          if(ogg_stream_pagein(&sh_audio->ov->os,&sh_audio->ov->og)<0)
-            mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Pagein failed!\n");
-          break;
-        } else if(ret<0) {
-          mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Packetout: missing or corrupt data, skipping packet!\n");
-          break;
-        } else {
+      case AFM_VORBIS: { // Vorbis
+        int samples;
+        float **pcm;
+        ogg_packet op;
+        char* np;
+        struct ov_struct_st *ov = sh_audio->context;
+        len = 0;
+        op.b_o_s =  op.e_o_s = 0;
+	while(len < minlen) {
+	  op.bytes = ds_get_packet(sh_audio->ds,&op.packet);
+	  if(!op.packet)
+	    break;
+	  if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */
+	    vorbis_synthesis_blockin(&ov->vd,&ov->vb);
+	  while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))>0){
+	    int i,j;
+	    int clipflag=0;
+	    int convsize=(maxlen-len)/(2*ov->vi.channels); // max size!
+	    int bout=(samples<convsize?samples:convsize);
+	  
+	    if(bout<=0) break;
 
-        /* we have a packet.  Decode it */
-	      
-	if(vorbis_synthesis(&sh_audio->ov->vb,&sh_audio->ov->op)==0) /* test for success! */
-	  vorbis_synthesis_blockin(&sh_audio->ov->vd,&sh_audio->ov->vb);
-	
-        /* **pcm is a multichannel float vector.  In stereo, for
-	   example, pcm[0] is left, and pcm[1] is right.  samples is
-	   the size of each channel.  Convert the float values
-	   (-1.<=range<=1.) to whatever PCM format and write it out */
-	      
-        while((samples=vorbis_synthesis_pcmout(&sh_audio->ov->vd,&pcm))>0){
-	  int i,j;
-	  int clipflag=0;
-	  int convsize=(maxlen-len)/(2*sh_audio->ov->vi.channels); // max size!
-	  int bout=(samples<convsize?samples:convsize);
-	  
-	  if(bout<=0) break;
-
-	  /* convert floats to 16 bit signed ints (host order) and
-	     interleave */
-	  for(i=0;i<sh_audio->ov->vi.channels;i++){
-    	    ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);
-	    ogg_int16_t *ptr=convbuffer+i;
-	    float  *mono=pcm[i];
-	    for(j=0;j<bout;j++){
+	    /* convert floats to 16 bit signed ints (host order) and
+	       interleave */
+	    for(i=0;i<ov->vi.channels;i++){
+	      ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);
+	      ogg_int16_t *ptr=convbuffer+i;
+	      float  *mono=pcm[i];
+	      for(j=0;j<bout;j++){
 #if 1
-	      int val=mono[j]*32767.f;
+		int val=mono[j]*32767.f;
 #else /* optional dither */
-	      int val=mono[j]*32767.f+drand48()-0.5f;
+		int val=mono[j]*32767.f+drand48()-0.5f;
 #endif
-	      /* might as well guard against clipping */
-	      if(val>32767){
-	        val=32767;
-	        clipflag=1;
+		/* might as well guard against clipping */
+		if(val>32767){
+		  val=32767;
+		  clipflag=1;
+		}
+		if(val<-32768){
+		  val=-32768;
+		  clipflag=1;
+		}
+		*ptr=val;
+		ptr+=ov->vi.channels;
 	      }
-	      if(val<-32768){
-	        val=-32768;
-	        clipflag=1;
-	      }
-	      *ptr=val;
-	      ptr+=sh_audio->ov->vi.channels;
 	    }
-	  }
 		
-	  if(clipflag)
-	    mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(sh_audio->ov->vd.sequence));
-	
-	  //fwrite(convbuffer,2*sh_audio->ov->vi.channels,bout,stderr); //dump pcm to file for debugging
-	  //memcpy(buf+len,convbuffer,2*sh_audio->ov->vi.channels*bout);
-          len+=2*sh_audio->ov->vi.channels*bout;
-	  
-	  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);
-	  
-	  vorbis_synthesis_read(&sh_audio->ov->vd,bout); /* tell libvorbis how
-							    many samples we
-							    actually consumed */
-        }
-        } // from else, packetout ok
-        } // while len
-        } // outer while len
-	if(ogg_page_eos(&sh_audio->ov->og))
-          mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: End of Stream reached!\n"); // FIXME clearup decoder, notify mplayer - atmos
-
-	mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[len: %d ]\n",len);
-
-        break;
-      }
+	    if(clipflag)
+	      mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence));
+	    len+=2*ov->vi.channels*bout;
+	    mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);
+	    vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how
+						    many samples we
+						    actually consumed */
+	  }
+	}
+      } break;
 #endif
       case AFM_PCM: // AVI PCM
         len=demux_read_data(sh_audio->ds,buf,minlen);
@@ -1337,13 +1217,6 @@
           MP3_DecodeFrame(NULL,-2); // resync
           MP3_DecodeFrame(NULL,-2); // resync
           break;
-#ifdef HAVE_OGGVORBIS
-        case AFM_VORBIS:
-          //printf("OggVorbis: resetting stream.\n");
-          ogg_sync_reset(&sh_audio->ov->oy);
-          ogg_stream_reset(&sh_audio->ov->os);
-          break;
-#endif
 #ifdef USE_LIBAC3
         case AFM_AC3:
           ac3_bitstream_reset();    // reset AC3 bitstream buffer
--- a/libmpdemux/Makefile	Sat Mar 16 06:01:13 2002 +0000
+++ b/libmpdemux/Makefile	Sat Mar 16 14:32:03 2002 +0000
@@ -3,7 +3,7 @@
 
 include ../config.mak
 
-SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c mpdemux.c
+SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c mpdemux.c demux_ogg.c
 ifeq ($(STREAMING),yes)
 SRCS += asf_streaming.c url.c http.c network.c rtp.c
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/demux_ogg.c	Sat Mar 16 14:32:03 2002 +0000
@@ -0,0 +1,597 @@
+
+#include "config.h"
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../mp_msg.h"
+#include "../help_mp.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+
+#ifndef HAVE_OGGVORBIS
+/// Some dummy function to use when no Ogg and Vorbis lib are avaible
+int demux_ogg_open(demuxer_t* demuxer) {
+  return 0;
+}
+
+int demux_ogg_fill_buffer(demuxer_t *d) {
+  return 0;
+}
+
+demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
+  mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_NoOggVorbis);
+  // disable audio
+  demuxer->audio->id = -2;
+  return demuxer;
+}
+#else
+
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+
+#define BLOCK_SIZE 1024
+
+/// Vorbis decoder context : we need the vorbis_info for vorbis timestamping
+/// Shall we put this struct def in a common header ?
+typedef struct ov_struct_st {
+  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
+			  settings */
+  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+  vorbis_block     vb; /* local working space for packet->PCM decode */
+} ov_struct_t;
+
+//// OggDS headers
+// Header for the new header format
+typedef struct stream_header_video
+{
+	ogg_int32_t	width;
+	ogg_int32_t	height;
+} stream_header_video;
+	
+typedef struct stream_header_audio
+{
+	ogg_int16_t	channels;
+	ogg_int16_t	blockalign;
+	ogg_int32_t	avgbytespersec;
+} stream_header_audio;
+
+typedef struct stream_header
+{
+	char	streamtype[8];
+	char	subtype[4];
+
+	ogg_int32_t	size;				// size of the structure
+
+	ogg_int64_t	time_unit;			// in reference time
+	ogg_int64_t	samples_per_unit;
+	ogg_int32_t default_len;		// in media time
+
+	ogg_int32_t buffersize;
+	ogg_int16_t	bits_per_sample;
+
+	union
+	{
+		// Video specific
+		stream_header_video	video;
+		// Audio specific
+		stream_header_audio	audio;
+	} sh;
+} stream_header;
+
+/// Our private datas
+
+/// A logical stream
+typedef struct ogg_stream {
+  /// Timestamping stuff
+  float samplerate; /// granulpos 2 time
+  int64_t lastpos;
+  int32_t lastsize;
+
+  // Logical stream state
+  ogg_stream_state stream;
+} ogg_stream_t;
+
+typedef struct ogg_demuxer {
+  /// Physical stream state
+  ogg_sync_state sync;
+  /// Current page
+  ogg_page page;
+  /// Logical streams
+  ogg_stream_t *subs;
+  int num_sub;
+} ogg_demuxer_t;
+
+/// Some defines from OggDS
+#define PACKET_TYPE_HEADER   0x01
+#define PACKET_TYPE_BITS         0x07
+#define PACKET_LEN_BITS01       0xc0
+#define PACKET_LEN_BITS2         0x02
+#define PACKET_IS_SYNCPOINT  0x08
+
+
+// get the logical stream of the current page
+// fill os if non NULL and return the stream id
+static  int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
+  int id,s_no;
+  ogg_page* page = &ogg_d->page;
+
+  s_no = ogg_page_serialno(page);
+
+  for(id= 0; id < ogg_d->num_sub ; id++) {
+    if(s_no == ogg_d->subs[id].stream.serialno)
+      break;
+  }
+
+  if(id == ogg_d->num_sub)
+    return -1;
+  
+  if(os)
+    *os = &ogg_d->subs[id].stream;
+
+  return id;
+
+}
+
+/// Calculate the timestamp and add the packet to the demux stream
+// return 1 if the packet was added, 0 otherwise
+static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,ogg_packet* pack) {
+  demuxer_t* d = ds->demuxer;
+  demux_packet_t* dp;
+  unsigned char* data;
+  float pts = 0;
+  int flags = 0;
+
+  // If packet is an header we jump it except for vorbis
+  if((*pack->packet & PACKET_TYPE_HEADER) && 
+     (ds == d->video || (ds == d->audio && ((sh_audio_t*)ds->sh)->format != 0xFFFE )))
+    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 == 0xFFFE) {
+    data = pack->packet;
+    if(*pack->packet & PACKET_TYPE_HEADER)
+      pts = 0;
+    else {
+      vorbis_info* vi = &((ov_struct_t*)((sh_audio_t*)ds->sh)->context)->vi;
+      // When we dump the audio, there is no vi, but we dont care of timestamp in this case
+      if(vi) {
+	int32_t blocksize = vorbis_packet_blocksize(vi,pack) / vi->channels;
+	// Calculate the timestamp if the packet don't have any
+	if(pack->granulepos == -1) {
+	  pack->granulepos = os->lastpos;
+	  if(os->lastsize > 0)
+	    pack->granulepos += os->lastsize;
+	}
+	pts = pack->granulepos / (float)vi->rate;
+	os->lastsize = blocksize;
+	os->lastpos = pack->granulepos;
+      }
+    }
+  } 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;
+    // If we alredy have a timestamp it can be a syncpoint
+    else 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;
+  }
+
+  /// Send the packet
+  dp = new_demux_packet(pack->bytes-(data-pack->packet));
+  memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
+  ds->pts = pts;
+  ds->flags = flags;
+  ds_add_packet(ds,dp);
+  return 1;
+}
+
+/// Open an ogg physical stream
+int 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;
+  ogg_sync_state* sync;
+  ogg_page* page;
+  ogg_packet pack;
+  sh_audio_t* sh_a;
+  sh_video_t* sh_v;
+
+  s = demuxer->stream;
+
+  ogg_d = (ogg_demuxer_t*)calloc(1,sizeof(ogg_demuxer_t));
+  sync = &ogg_d->sync;
+  page = &ogg_d->page;
+
+  ogg_sync_init(&ogg_d->sync);
+
+  while(1) {
+    /// Try to get a page
+    np = ogg_sync_pageout(sync,page);
+    /// Error
+    if(np < 0) {
+      mp_msg(MSGT_DEMUX,MSGL_DBG2,"OGG demuxer : Bad page sync\n");
+      return 0;
+    }
+    /// Need some more data
+    if(np <= 0) {
+      int len;
+      buf = ogg_sync_buffer(sync,BLOCK_SIZE);
+      len = stream_read(s,buf,BLOCK_SIZE);      
+      if(len == 0 && s->eof) {
+	free(ogg_d);
+	return 0;
+      }
+      ogg_sync_wrote(sync,len);
+      continue;
+    }
+
+    // We got one page now
+
+    if( ! ogg_page_bos(page) ) { // It's not a begining page
+      // Header parsing end here, we need to get the page otherwise it will be lost
+      int id = demux_ogg_get_page_stream(ogg_d,NULL);
+      if(id >= 0)
+	ogg_stream_pagein(&ogg_d->subs[id].stream,page);
+      else
+	mp_msg(MSGT_DEMUX,MSGL_ERR,"OGG : Warning found none bos page from unknow stream %d\n",ogg_page_serialno(page));
+      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;
+
+    // Check for Vorbis
+    if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
+      sh_a = new_sh_audio(demuxer,ogg_d->num_sub);
+      sh_a->format = 0xFFFE;
+      n_audio++;
+      mp_msg(MSGT_DEMUX,MSGL_V,"OGG : stream %d is vorbis\n",ogg_d->num_sub);
+
+      /// Check for old header
+    } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
+
+       // Old video header
+      if(*(int32_t*)(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
+	sh_v = new_sh_video(demuxer,ogg_d->num_sub);
+	sh_v->bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER));
+	sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
+				pack.packet[70],pack.packet[71]);
+	sh_v->frametime =  (*(int64_t*)(pack.packet+164))*0.0000001;
+	sh_v->fps = 1/sh_v->frametime;
+	sh_v->disp_w = sh_v->bih->biWidth = *(int32_t*)(pack.packet+176);
+	sh_v->disp_h = sh_v->bih->biHeight = *(int32_t*)(pack.packet+180);
+	sh_v->bih->biBitCount = *(int16_t*)(pack.packet+182);
+
+	ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
+	n_video++;
+	mp_msg(MSGT_DEMUX,MSGL_V,"OGG stream %d is video\n",ogg_d->num_sub);
+
+	// Old audio header
+      } else if(*(int32_t*)pack.packet+96 == 0x05589F81) {
+	unsigned int extra_size;
+	sh_a = new_sh_audio(demuxer,ogg_d->num_sub);
+	extra_size = *(int16_t*)(pack.packet+140);
+	sh_a->wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX)+extra_size);
+	sh_a->format = sh_a->wf->wFormatTag = *(int16_t*)(pack.packet+124);
+	sh_a->channels = sh_a->wf->nChannels = *(int16_t*)(pack.packet+126);
+	sh_a->samplerate = sh_a->wf->nSamplesPerSec = *(int32_t*)(pack.packet+128);
+	sh_a->wf->nAvgBytesPerSec = *(int32_t*)(pack.packet+132);
+	sh_a->wf->nBlockAlign = *(int16_t*)(pack.packet+136);
+	sh_a->wf->wBitsPerSample = *(int16_t*)(pack.packet+138);
+	sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
+	sh_a->wf->cbSize = extra_size;
+	if(extra_size > 0)
+	  memcpy(sh_a->wf+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
+
+	ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate * sh_a->channels;
+	n_audio++;
+	mp_msg(MSGT_DEMUX,MSGL_V,"OGG stream %d is audio\n",ogg_d->num_sub);
+      } else
+	mp_msg(MSGT_DEMUX,MSGL_WARN,"OGG stream %d contain an old header but the header type is unknow\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(demuxer,ogg_d->num_sub);
+	sh_v->bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER));
+	sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
+				  st->subtype[2],st->subtype[3]);
+	sh_v->frametime = st->time_unit*0.0000001;
+	sh_v->fps = 1/sh_v->frametime;
+	sh_v->bih->biSize = st->buffersize;
+	sh_v->bih->biBitCount = st->bits_per_sample;
+	sh_v->disp_w = sh_v->bih->biWidth = st->sh.video.width;
+	sh_v->disp_h = sh_v->bih->biHeight = st->sh.video.height;
+
+	ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
+	n_video++;
+	mp_msg(MSGT_DEMUX,MSGL_V,"OGG stream %d is video\n",ogg_d->num_sub);
+	/// New audio header
+      } else if(strncmp(st->streamtype,"audio",5) == 0) {
+	char buffer[5];
+	unsigned int extra_size = st->size - sizeof(stream_header);
+	memcpy(buffer,st->subtype,4);
+	buffer[4] = '\0';
+	sh_a = new_sh_audio(demuxer,ogg_d->num_sub);
+	sh_a->wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX)+extra_size);
+	sh_a->format =  sh_a->wf->wFormatTag = atoi(buffer);
+	sh_a->channels = sh_a->wf->nChannels = st->sh.audio.channels;
+	sh_a->samplerate = sh_a->wf->nSamplesPerSec = st->samples_per_unit;
+	sh_a->wf->nAvgBytesPerSec = st->sh.audio.avgbytespersec;
+	sh_a->wf->nBlockAlign = st->sh.audio.blockalign;
+	sh_a->wf->wBitsPerSample = st->bits_per_sample;
+	sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
+	sh_a->wf->cbSize = extra_size;
+	if(extra_size)
+	  memcpy(sh_a->wf+sizeof(WAVEFORMATEX),st+1,extra_size);
+
+	ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate * sh_a->channels;
+	n_audio++;
+	mp_msg(MSGT_DEMUX,MSGL_V,"OGG stream %d is audio\n",ogg_d->num_sub);
+
+	/// Check for text (subtitles) header
+      } else if(strncmp(st->streamtype,"text",4) == 0) {
+	mp_msg(MSGT_DEMUX,MSGL_WARN,"OGG text stream are not supported\n");
+	//// Unknow header type
+      } else
+	mp_msg(MSGT_DEMUX,MSGL_ERR,"OGG stream %d has a header marker but is of an unknow type\n",ogg_d->num_sub);
+      /// Unknow (invalid ?) header
+    } else
+      mp_msg(MSGT_DEMUX,MSGL_ERR,"OGG stream %d is of an unknow 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 = ogg_d->num_sub;
+	  demuxer->audio->sh = sh_a;
+	  sh_a->ds = demuxer->audio;
+	}
+	/// Is it the stream we want
+	if(demuxer->audio->id == ogg_d->num_sub)
+	  ds = demuxer->audio;
+      }
+      if(sh_v) {
+	/// Also for video
+	if(demuxer->video->id == -1) {
+	  demuxer->video->id = ogg_d->num_sub;
+	  demuxer->video->sh = sh_v;
+	  sh_v->ds = demuxer->video;
+	}
+	if(demuxer->video->id == ogg_d->num_sub)
+	  ds = demuxer->video;
+      }
+      /// Add the packet contained in this page
+       if(ds) {
+	 /// Finish the page, otherwise packets will be lost
+	 do {
+	   demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],&pack);
+	 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
+	 
+       }
+    }
+    ogg_d->num_sub++;      
+  }
+
+  /// Finish to setup the demuxer
+  demuxer->priv = ogg_d;
+  /// We can't seek :(
+  demuxer->seekable = 0;
+
+  if(!n_video)
+    demuxer->video->id = -2;
+  if(!n_audio)
+    demuxer->audio->id = -2;
+
+  mp_msg(MSGT_DEMUX,MSGL_V,"OGG demuxer : found %d audio stream and %d video stream\n",n_audio,n_video);
+ 
+  return 1;
+}
+
+
+int demux_ogg_fill_buffer(demuxer_t *d) {
+  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;
+	  /// Get the next page from the physical stream
+	  while( (pa = ogg_sync_pageout(sync,page)) != 1) {
+	    /// Error : we skip some bytes
+	    if(pa < 0) {
+	      mp_msg(MSGT_DEMUX,MSGL_WARN,"OGG : Page out not synced, we skip some bytes\n");
+	      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
+
+	  /// 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 unknow 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");
+	}
+      } 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;
+
+    if(ds) {
+      if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],&pack))
+	continue; /// Unuseful packet, get another
+      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 demuxer
+demuxer_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 < 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)+2*sizeof(WAVEFORMATEX), 3*sizeof(uint32_t));
+
+  /// Check the size
+  if(sh_audio->wf->cbSize < 3*sizeof(uint32_t) + 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));
+
+   // 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)+2*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)+2*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)+2*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 = 0xFFFE;
+
+  /// Return the joined demuxers
+  return new_demuxers_demuxer(demuxer,od,demuxer);
+
+ fallback:
+  demuxer->audio->id = -2;
+  return demuxer;
+
+}
+
+/// TODO : Seeking 8-)
+  
+#endif
--- a/libmpdemux/demuxer.c	Sat Mar 16 06:01:13 2002 +0000
+++ b/libmpdemux/demuxer.c	Sat Mar 16 14:32:03 2002 +0000
@@ -218,6 +218,7 @@
 int demux_y4m_fill_buffer(demuxer_t *demux);
 int demux_audio_fill_buffer(demux_stream_t *ds);
 extern int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds);
+extern int demux_ogg_fill_buffer(demuxer_t *d);
 
 int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){
   // Note: parameter 'ds' can be NULL!
@@ -243,6 +244,7 @@
     case DEMUXER_TYPE_Y4M: return demux_y4m_fill_buffer(demux);
     case DEMUXER_TYPE_AUDIO: return demux_audio_fill_buffer(ds);
     case DEMUXER_TYPE_DEMUXERS: return demux_demuxers_fill_buffer(demux,ds);
+    case DEMUXER_TYPE_OGG: return demux_ogg_fill_buffer(demux);
   }
   return 0;
 }
@@ -434,6 +436,9 @@
 extern int nuv_check_file(demuxer_t *demuxer);
 extern void demux_open_nuv(demuxer_t *demuxer);
 extern int demux_audio_open(demuxer_t* demuxer);
+extern int demux_ogg_open(demuxer_t* demuxer);
+
+extern demuxer_t* init_avi_with_ogg(demuxer_t* demuxer);
 
 
 static demuxer_t* demux_open_stream(stream_t *stream,int file_format,int audio_id,int video_id,int dvdsub_id){
@@ -593,6 +598,17 @@
       demuxer = NULL;
   }
 }
+//=============== Try to open as Ogg file: =================
+if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_OGG){
+  demuxer=new_demuxer(stream,DEMUXER_TYPE_OGG,audio_id,video_id,dvdsub_id);
+  if(demux_ogg_open(demuxer)){
+      mp_msg(MSGT_DEMUXER,MSGL_INFO,"Detected OGG format\n");
+      file_format=DEMUXER_TYPE_OGG;
+  } else {
+      free_demuxer(demuxer);
+      demuxer = NULL;
+  }
+}
 //=============== Try to open as MPEG-PS file: =================
 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_PS){
  int pes=1;
@@ -719,7 +735,12 @@
   break;
  }
  case DEMUXER_TYPE_AVI: {
-  return (demuxer_t*) demux_open_avi(demuxer);
+   sh_audio_t* sh_a;
+   demuxer = (demuxer_t*) demux_open_avi(demuxer);
+   sh_a = (sh_audio_t*)demuxer->audio->sh;
+   if(demuxer->audio->id != -2 && sh_a && sh_a->format == 0xFFFE)
+     demuxer = init_avi_with_ogg(demuxer);
+   return demuxer;
 //  break;
  }
  case DEMUXER_TYPE_NUV: {
--- a/libmpdemux/demuxer.h	Sat Mar 16 06:01:13 2002 +0000
+++ b/libmpdemux/demuxer.h	Sat Mar 16 14:32:03 2002 +0000
@@ -22,9 +22,10 @@
 #define DEMUXER_TYPE_ROQ 15
 #define DEMUXER_TYPE_MF 16
 #define DEMUXER_TYPE_AUDIO 17
+#define DEMUXER_TYPE_OGG 18
 // This should always match the higest demuxer type number.
 // Unless you want to disallow users to force the demuxer to some types
-#define DEMUXER_TYPE_MAX 17
+#define DEMUXER_TYPE_MAX 18
 
 #define DEMUXER_TYPE_DEMUXERS (1<<16)
 // A virtual demuxer type for the network code
@@ -167,6 +168,8 @@
 int ds_get_packet(demux_stream_t *ds,unsigned char **start);
 int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start);
 
+// This is defined here because demux_stream_t ins't defined in stream.h
+stream_t* new_ds_stream(demux_stream_t *ds);
 
 static inline int avi_stream_id(unsigned int id){
   unsigned char *p=(unsigned char *)&id;
--- a/libmpdemux/stream.c	Sat Mar 16 06:01:13 2002 +0000
+++ b/libmpdemux/stream.c	Sat Mar 16 14:32:03 2002 +0000
@@ -14,6 +14,7 @@
 #include "help_mp.h"
 
 #include "stream.h"
+#include "demuxer.h"
 
 extern int verbose; // defined in mplayer.c
 
@@ -75,6 +76,9 @@
     break;
   }
 #endif
+  case STREAMTYPE_DS:
+    len = demux_read_data((demux_stream_t*)s->priv,s->buffer,STREAM_BUFFER_SIZE);
+    break;
   default: len=0;
   }
   if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
@@ -236,3 +240,8 @@
   free(s);
 }
 
+stream_t* new_ds_stream(demux_stream_t *ds) {
+  stream_t* s = new_stream(-1,STREAMTYPE_DS);
+  s->priv = ds;
+  return s;
+}
--- a/libmpdemux/stream.h	Sat Mar 16 06:01:13 2002 +0000
+++ b/libmpdemux/stream.h	Sat Mar 16 14:32:03 2002 +0000
@@ -14,6 +14,7 @@
 #define STREAMTYPE_TV	5
 #define STREAMTYPE_PLAYLIST 6
 #define STREAMTYPE_MF   7
+#define STREAMTYPE_DS   8
 
 #define VCD_SECTOR_SIZE 2352
 #define VCD_SECTOR_OFFS 24