summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2002-08-19 22:12:52 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2002-08-19 22:12:52 +0000
commitffcc3013d310385865dda30c53519cb635f5b8cc (patch)
treee06b5ceb269cce74a607accb0d7b6e7f7aa03e41
parentdf9fbd464983226833a1a8c184a82f35af278dbc (diff)
downloadxine-lib-ffcc3013d310385865dda30c53519cb635f5b8cc.tar.gz
xine-lib-ffcc3013d310385865dda30c53519cb635f5b8cc.tar.bz2
xine now survives all ogm test streams i got :) - including seeking (though not perfect)
CVS patchset: 2489 CVS date: 2002/08/19 22:12:52
-rw-r--r--src/demuxers/demux_ogg.c353
-rw-r--r--src/libvorbis/xine_decoder.c136
2 files changed, 273 insertions, 216 deletions
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
index 865908526..607a3f20d 100644
--- a/src/demuxers/demux_ogg.c
+++ b/src/demuxers/demux_ogg.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: demux_ogg.c,v 1.33 2002/08/18 14:13:08 guenter Exp $
+ * $Id: demux_ogg.c,v 1.34 2002/08/19 22:12:52 guenter Exp $
*
* demultiplexer for ogg streams
*
@@ -118,6 +118,9 @@ typedef struct demux_ogg_s {
int samplerate[MAX_STREAMS];
int num_streams;
+ int num_audio_streams;
+ int num_video_streams;
+
int avg_bitrate;
} demux_ogg_t ;
@@ -153,6 +156,131 @@ static void hex_dump (uint8_t *p, int length) {
}
+/*
+ * utility function to pack one ogg_packet into a xine
+ * buffer, fill out all needed fields
+ * and send it to the right fifo
+ */
+
+static void send_ogg_buf (demux_ogg_t *this,
+ ogg_packet *op,
+ int stream_num,
+ uint32_t decoder_flags) {
+
+ if ( this->audio_fifo
+ && (this->buf_types[stream_num] & 0xFF000000) == BUF_AUDIO_BASE) {
+ buf_element_t *buf;
+
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+
+ if ((this->buf_types[stream_num] & 0xFFFF0000) == BUF_AUDIO_VORBIS) {
+ int op_size = sizeof(ogg_packet);
+ ogg_packet *og_ghost;
+ op_size += (4 - (op_size % 4));
+
+#ifdef LOG
+ printf ("demux_ogg: special treatment for vorbis package\n");
+ hex_dump (op->packet, op->bytes);
+#endif
+
+ /* nasty hack to pack op as well as (vorbis) content
+ in one xine buffer */
+ memcpy (buf->content + op_size, op->packet, op->bytes);
+ memcpy (buf->content, op, op_size);
+ og_ghost = (ogg_packet *) buf->content;
+ og_ghost->packet = buf->content + op_size;
+
+ buf->size = op->bytes;
+ } else {
+ int hdrlen;
+
+ hdrlen = (*op->packet & PACKET_LEN_BITS01) >> 6;
+ hdrlen |= (*op->packet & PACKET_LEN_BITS2) << 1;
+
+#ifdef LOG
+ printf ("demux_ogg: headerlen %d\n",hdrlen);
+#endif
+
+ memcpy (buf->content, op->packet+1+hdrlen, op->bytes-1-hdrlen);
+ buf->size = op->bytes-1-hdrlen;
+ }
+
+#ifdef LOG
+ printf ("demux_ogg: audio buf_size %d\n", buf->size);
+#endif
+
+ if (op->granulepos>0)
+ buf->pts = 90000 * op->granulepos / this->samplerate[stream_num];
+ else
+ buf->pts = 0;
+
+#ifdef LOG
+ printf ("demux_ogg: audio granulepos %lld => pts %lld\n",
+ op->granulepos, buf->pts);
+#endif
+
+ buf->input_pos = this->input->get_current_pos (this->input);
+ buf->input_time = buf->input_pos * 8 / this->avg_bitrate;
+ buf->type = this->buf_types[stream_num] ;
+ buf->decoder_flags = decoder_flags;
+
+ this->audio_fifo->put (this->audio_fifo, buf);
+
+ } else if ((this->buf_types[stream_num] & 0xFF000000) == BUF_VIDEO_BASE) {
+
+ buf_element_t *buf;
+ int todo, done, hdrlen;
+
+#ifdef LOG
+ printf ("demux_ogg: video buffer, type=%08x\n", this->buf_types[stream_num]);
+#endif
+
+ hdrlen = (*op->packet & PACKET_LEN_BITS01) >> 6;
+ hdrlen |= (*op->packet & PACKET_LEN_BITS2) << 1;
+
+#ifdef LOG
+ printf ("demux_ogg: headerlen %d\n",hdrlen);
+#endif
+
+ todo = op->bytes-1-hdrlen;
+ done = 0;
+ while (done<todo) {
+
+ buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+
+ if ( (todo-done)>(buf->max_size-1)) {
+ buf->size = buf->max_size-1;
+ buf->decoder_flags = decoder_flags;
+ } else {
+ buf->size = todo-done;
+ buf->decoder_flags = BUF_FLAG_FRAME_END | decoder_flags;
+ }
+
+ /*
+ printf ("demux_ogg: done %d todo %d doing %d\n", done, todo, buf->size);
+ */
+ memcpy (buf->content, op->packet+done, buf->size);
+
+ if (op->granulepos>0)
+ buf->pts = op->granulepos * this->frame_duration;
+ else
+ buf->pts = 0;
+#ifdef LOG
+ printf ("demux_ogg: video granulepos %lld, pts %lld\n", op->granulepos, buf->pts);
+#endif
+
+ buf->input_pos = this->input->get_current_pos (this->input);
+ buf->input_time = 0;
+ buf->type = this->buf_types[stream_num] ;
+
+ done += buf->size;
+
+ this->video_fifo->put (this->video_fifo, buf);
+
+ }
+ }
+}
+
/*
* interpret strea start packages, send headers
*/
@@ -164,16 +292,18 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
char *buffer;
long bytes;
- ogg_packet op;
-
- while (1) {
+ int num_preview_buffers = 50;
- int ret = ogg_sync_pageout(&this->oy,&this->og);
+ ogg_packet op;
#ifdef LOG
- printf ("demux_ogg: send header...\n");
+ printf ("demux_ogg: detecting stream types...\n");
#endif
+ while (num_preview_buffers>0) {
+
+ int ret = ogg_sync_pageout(&this->oy,&this->og);
+
if (ret == 0) {
buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE);
bytes = this->input->read(this->input, buffer, CHUNKSIZE);
@@ -189,25 +319,38 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
cur_serno = ogg_page_serialno (&this->og);
- if (!ogg_page_bos(&this->og)) {
-#ifdef LOG
- printf ("demux_ogg: beginning of content found\n");
-#endif
- return;
- }
+ stream_num = -1;
+
+ if (ogg_page_bos(&this->og)) {
- printf ("demux_ogg: beginning of stream\ndemux_ogg: serial number %d\n",
- cur_serno);
+ printf ("demux_ogg: beginning of stream\ndemux_ogg: serial number %d\n",
+ cur_serno);
- ogg_stream_init(&this->oss[this->num_streams], cur_serno);
- stream_num = this->num_streams;
- this->buf_types[stream_num] = 0;
- this->num_streams++;
+ ogg_stream_init(&this->oss[this->num_streams], cur_serno);
+ stream_num = this->num_streams;
+ this->buf_types[stream_num] = 0;
+ this->num_streams++;
+ } else {
+ int i;
+
+ for (i = 0; i<this->num_streams; i++) {
+ if (this->oss[i].serialno == cur_serno) {
+ stream_num = i;
+ break;
+ }
+ }
+ if (stream_num == -1) {
+ printf ("demux_ogg: help, stream with no beginning!\n");
+ abort();
+ }
+ }
ogg_stream_pagein(&this->oss[stream_num], &this->og);
while (ogg_stream_packetout(&this->oss[stream_num], &op) == 1) {
+ printf ("demux_ogg: packet of stream %d found\n", cur_serno);
+
if (!this->buf_types[stream_num]) {
/* detect buftype */
if (!strncmp (&op.packet[1], "vorbis", 6)) {
@@ -215,7 +358,8 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
vorbis_info vi;
vorbis_comment vc;
- this->buf_types[stream_num] = BUF_AUDIO_VORBIS;
+ this->buf_types[stream_num] = BUF_AUDIO_VORBIS
+ +this->num_audio_streams++;
xine_log (this->xine, XINE_LOG_FORMAT,
_("ogg: vorbis audio stream detected\n"));
@@ -230,7 +374,10 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
this->samplerate[stream_num] = vi.rate;
- this->avg_bitrate += vi.bitrate_nominal;
+ if (vi.bitrate_nominal<1)
+ this->avg_bitrate += 100000; /* assume 100 kbit */
+ else
+ this->avg_bitrate += vi.bitrate_nominal;
} else {
this->samplerate[stream_num] = 44100;
@@ -243,6 +390,7 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
dsogg_header_t *oggh;
buf_element_t *buf;
xine_bmiheader bih;
+ int channel;
#ifdef LOG
printf ("demux_ogg: direct show filter created stream detected, hexdump:\n");
@@ -251,7 +399,9 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
oggh = (dsogg_header_t *) &op.packet[1];
- this->buf_types[stream_num] = fourcc_to_buf_video (oggh->subtype);
+ channel = this->num_video_streams++;
+
+ this->buf_types[stream_num] = fourcc_to_buf_video (oggh->subtype) | channel;
#ifdef LOG
printf ("demux_ogg: subtype %.4s\n", &oggh->subtype);
@@ -292,6 +442,7 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
buf_element_t *buf;
int codec;
char str[5];
+ int channel;
printf ("demux_ogg: direct show filter created audio stream detected, hexdump:\n");
hex_dump (op.packet, op.bytes);
@@ -302,21 +453,23 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
str[4] = 0;
codec = atoi(str);
+ channel= this->num_audio_streams++;
+
switch (codec) {
case 0x01:
- this->buf_types[stream_num] = BUF_AUDIO_LPCM_LE;
+ this->buf_types[stream_num] = BUF_AUDIO_LPCM_LE | channel;
break;
case 55:
case 0x55:
- this->buf_types[stream_num] = BUF_AUDIO_MPEG;
+ this->buf_types[stream_num] = BUF_AUDIO_MPEG | channel;
break;
case 0x2000:
- this->buf_types[stream_num] = BUF_AUDIO_A52;
+ this->buf_types[stream_num] = BUF_AUDIO_A52 | channel;
break;
default:
printf ("demux_ogg: unknown audio codec type 0x%x\n",
codec);
- this->buf_types[stream_num] = 0;
+ this->buf_types[stream_num] = BUF_CONTROL_NOP;
break;
}
@@ -355,12 +508,27 @@ static void demux_ogg_send_header (demux_ogg_t *this) {
this->buf_types[stream_num] = BUF_CONTROL_NOP;
}
}
+
+ /*
+ * send preview buffer
+ */
+
+#ifdef LOG
+ printf ("demux_ogg: sending preview buffer of stream type %08x\n",
+ this->buf_types[stream_num]);
+#endif
+
+ send_ogg_buf (this, &op, stream_num, BUF_FLAG_PREVIEW);
+
+ if (!ogg_page_bos(&this->og))
+ num_preview_buffers --;
+
}
}
}
}
-static void demux_ogg_send_package (demux_ogg_t *this) {
+static void demux_ogg_send_content (demux_ogg_t *this) {
int i;
int stream_num = -1;
@@ -421,130 +589,15 @@ static void demux_ogg_send_package (demux_ogg_t *this) {
while (ogg_stream_packetout(&this->oss[stream_num], &op) == 1) {
/* printf("demux_ogg: packet: %.8s\n", op.packet); */
/* printf("demux_ogg: got a packet\n"); */
-
- if ( this->audio_fifo
- && (this->buf_types[stream_num] & 0xFF000000) == BUF_AUDIO_BASE) {
- buf_element_t *buf;
-
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
-
- if (this->buf_types[stream_num] == BUF_AUDIO_VORBIS) {
- int op_size = sizeof(op);
- ogg_packet *og_ghost;
- op_size += (4 - (op_size % 4));
-
- /* nasty hack to pack op as well as (vorbis) content
- in one xine buffer */
- memcpy (buf->content + op_size, op.packet, op.bytes);
- memcpy (buf->content, &op, sizeof(op));
- og_ghost = (ogg_packet *) buf->content;
- og_ghost->packet = buf->content + op_size;
-
- buf->size = op.bytes;
- } else {
- int hdrlen;
- if (*op.packet & PACKET_TYPE_HEADER) {
-#ifdef LOG
- printf ("demux_ogg: header\n");
-#endif
- buf->free_buffer(buf);
- continue;
- }
-
- hdrlen = (*op.packet & PACKET_LEN_BITS01) >> 6;
- hdrlen |= (*op.packet & PACKET_LEN_BITS2) << 1;
-
-#ifdef LOG
- printf ("demux_ogg: headerlen %d\n",hdrlen);
-#endif
-
- memcpy (buf->content, op.packet+1+hdrlen, op.bytes-1-hdrlen);
- buf->size = op.bytes-1-hdrlen;
- }
-
-#ifdef LOG
- printf ("demux_ogg: audio buf_size %d\n", buf->size);
-#endif
-
- if (op.granulepos>0)
- buf->pts = 90000 * op.granulepos / this->samplerate[stream_num];
- else
- buf->pts = 0;
-
-#ifdef LOG
- printf ("demux_ogg: audio granulepos %lld => pts %lld\n",
- op.granulepos, buf->pts);
-#endif
-
- buf->input_pos = this->input->get_current_pos (this->input);
- buf->input_time = buf->input_pos * 8 / this->avg_bitrate;
-
- buf->type = this->buf_types[stream_num];
-
- this->audio_fifo->put (this->audio_fifo, buf);
- } else if ((this->buf_types[stream_num] & 0xFF000000) == BUF_VIDEO_BASE) {
-
- buf_element_t *buf;
- int todo, done, hdrlen;
-
-#ifdef LOG
- printf ("demux_ogg: video buffer, type=%08x\n", this->buf_types[stream_num]);
-#endif
-
- if (*op.packet & PACKET_TYPE_HEADER) {
+ if (*op.packet & PACKET_TYPE_HEADER) {
#ifdef LOG
- printf ("demux_ogg: header\n");
+ printf ("demux_ogg: header => discard\n");
#endif
- continue;
- }
-
- hdrlen = (*op.packet & PACKET_LEN_BITS01) >> 6;
- hdrlen |= (*op.packet & PACKET_LEN_BITS2) << 1;
-
-#ifdef LOG
- printf ("demux_ogg: headerlen %d\n",hdrlen);
-#endif
-
- todo = op.bytes-1-hdrlen;
- done = 0;
- while (done<todo) {
-
- buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
-
- if ( (todo-done)>(buf->max_size-1)) {
- buf->size = buf->max_size-1;
- buf->decoder_flags = 0;
- } else {
- buf->size = todo-done;
- buf->decoder_flags = BUF_FLAG_FRAME_END;
- }
-
- /*
- printf ("demux_ogg: done %d todo %d doing %d\n", done, todo, buf->size);
- */
- memcpy (buf->content, op.packet+done, buf->size);
-
- if (op.granulepos>0)
- buf->pts = op.granulepos * this->frame_duration;
- else
- buf->pts = 0;
-#ifdef LOG
- printf ("demux_ogg: video granulepos %lld, pts %lld\n", op.granulepos, buf->pts);
-#endif
- /* buf->pts = 0; */
-
- buf->input_pos = this->input->get_current_pos (this->input);
- buf->input_time = 0;
-
- buf->type = this->buf_types[stream_num];
-
- done += buf->size;
-
- this->video_fifo->put (this->video_fifo, buf);
-
- }
+ continue;
}
+
+ send_ogg_buf (this, &op, stream_num, 0);
}
}
}
@@ -563,7 +616,7 @@ static void *demux_ogg_loop (void *this_gen) {
/* main demuxer loop */
while(this->status == DEMUX_OK) {
- demux_ogg_send_package (this);
+ demux_ogg_send_content (this);
/* someone may want to interrupt us */
pthread_mutex_unlock( &this->mutex );
@@ -663,8 +716,10 @@ static int demux_ogg_start (demux_plugin_t *this_gen,
*/
ogg_sync_init(&this->oy);
- this->num_streams = 0;
- this->avg_bitrate = 1;
+ this->num_streams = 0;
+ this->num_audio_streams = 0;
+ this->num_video_streams = 0;
+ this->avg_bitrate = 1;
this->input->seek (this->input, 0, SEEK_SET);
diff --git a/src/libvorbis/xine_decoder.c b/src/libvorbis/xine_decoder.c
index 5e6d1d00a..5cda59cdd 100644
--- a/src/libvorbis/xine_decoder.c
+++ b/src/libvorbis/xine_decoder.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.14 2002/07/05 17:32:04 mroi Exp $
+ * $Id: xine_decoder.c,v 1.15 2002/08/19 22:12:54 guenter Exp $
*
* (ogg/)vorbis audio decoder plugin (libvorbis wrapper) for xine
*/
@@ -38,6 +38,10 @@
#define MAX_NUM_SAMPLES 4096
+/*
+#define LOG
+*/
+
typedef struct vorbis_decoder_s {
audio_decoder_t audio_decoder;
@@ -86,8 +90,9 @@ static void vorbis_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
vorbis_info_init(&this->vi);
vorbis_comment_init(&this->vc);
-
+#ifdef LOG
printf ("libvorbis: init\n");
+#endif
}
@@ -96,84 +101,81 @@ static void vorbis_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
vorbis_decoder_t *this = (vorbis_decoder_t *) this_gen;
ogg_packet *op = (ogg_packet *) buf->content;
- /*
- printf ("vorbisdecoder: before buf=%08x content=%08x op=%08x packet=%08x\n",
- buf, buf->content, op, op->packet);
- */
+#ifdef LOG
+ printf ("libvorbis: decode buf=%08x content=%08x op=%08x packet=%08x flags=%08x\n",
+ buf, buf->content, op, op->packet, buf->decoder_flags);
+#endif
- if (buf->decoder_flags & BUF_FLAG_PREVIEW)
- return;
-
- /* if (buf->decoder_info[0] >0) { */
-
-
- if (this->header_count) {
+ if (buf->decoder_flags & BUF_FLAG_PREVIEW) {
+#ifdef LOG
+ printf ("libvorbis: preview buffer\n");
+#endif
+ if (this->header_count) {
- if(vorbis_synthesis_headerin(&this->vi,&this->vc,op)<0){
- /* error case; not a vorbis header */
- printf("libvorbis: this bitstream does not contain Vorbis "
- "audio data.\n");
- /* FIXME: handle error */
- }
+ if(vorbis_synthesis_headerin(&this->vi,&this->vc,op)<0){
+ /* error case; not a vorbis header */
+ printf("libvorbis: this bitstream does not contain vorbis audio data.\n");
+ return;
+ }
- this->header_count--;
+ this->header_count--;
- if (!this->header_count) {
+ if (!this->header_count) {
- int mode = AO_CAP_MODE_MONO;
-
- {
- char **ptr=this->vc.user_comments;
- while(*ptr){
- printf("libvorbis: %s\n",*ptr);
- ++ptr;
+ int mode = AO_CAP_MODE_MONO;
+
+ {
+ char **ptr=this->vc.user_comments;
+ while(*ptr){
+ printf("libvorbis: %s\n",*ptr);
+ ++ptr;
+ }
+ printf ("\nlibvorbis: bitstream is %d channel(s), %ldHz\n",
+ this->vi.channels, this->vi.rate);
+ printf("libvorbis: encoded by: %s\n\n",this->vc.vendor);
}
- printf ("\nlibvorbis: bitstream is %d channel, %ldHz\n",
- this->vi.channels, this->vi.rate);
- printf("libvorbis: encoded by: %s\n\n",this->vc.vendor);
- }
-
- switch (this->vi.channels) {
- case 1:
- mode = AO_CAP_MODE_MONO;
- break;
- case 2:
- mode = AO_CAP_MODE_STEREO;
- break;
- case 4:
- mode = AO_CAP_MODE_4CHANNEL;
- break;
- case 5:
- mode = AO_CAP_MODE_5CHANNEL;
- break;
- case 6:
- mode = AO_CAP_MODE_5_1CHANNEL;
- break;
- default:
- printf ("libvorbis: help, %d channels ?!\n",
- this->vi.channels);
- /* FIXME: handle error */
- }
-
- this->convsize=MAX_NUM_SAMPLES/this->vi.channels;
-
- if (!this->output_open) {
- this->output_open = this->audio_out->open(this->audio_out,
- 16,
- this->vi.rate,
- mode) ;
+
+ switch (this->vi.channels) {
+ case 1:
+ mode = AO_CAP_MODE_MONO;
+ break;
+ case 2:
+ mode = AO_CAP_MODE_STEREO;
+ break;
+ case 4:
+ mode = AO_CAP_MODE_4CHANNEL;
+ break;
+ case 5:
+ mode = AO_CAP_MODE_5CHANNEL;
+ break;
+ case 6:
+ mode = AO_CAP_MODE_5_1CHANNEL;
+ break;
+ default:
+ printf ("libvorbis: help, %d channels ?!\n",
+ this->vi.channels);
+ /* FIXME: handle error */
+ }
+
+ this->convsize=MAX_NUM_SAMPLES/this->vi.channels;
+
+ if (!this->output_open) {
+ this->output_open = this->audio_out->open(this->audio_out,
+ 16,
+ this->vi.rate,
+ mode) ;
+ }
+
+ vorbis_synthesis_init(&this->vd,&this->vi);
+ vorbis_block_init(&this->vd,&this->vb);
}
-
- vorbis_synthesis_init(&this->vd,&this->vi);
- vorbis_block_init(&this->vd,&this->vb);
-
}
+
} else if (this->output_open) {
float **pcm;
int samples;
-
if(vorbis_synthesis(&this->vb,op)==0)
vorbis_synthesis_blockin(&this->vd,&this->vb);