diff options
Diffstat (limited to 'src/demuxers/demux_ogg.c')
-rw-r--r-- | src/demuxers/demux_ogg.c | 316 |
1 files changed, 172 insertions, 144 deletions
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 7a349f1d5..42a7bc03b 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.47 2002/10/26 22:00:53 guenter Exp $ + * $Id: demux_ogg.c,v 1.48 2002/10/27 01:52:15 guenter Exp $ * * demultiplexer for ogg streams * @@ -62,8 +62,6 @@ #define WRAP_THRESHOLD 220000 -#define VALID_ENDS "ogg,ogm" - typedef struct dsogg_video_header_s { int32_t width; int32_t height; @@ -100,10 +98,8 @@ typedef struct { typedef struct demux_ogg_s { demux_plugin_t demux_plugin; - xine_t *xine; + xine_stream_t *stream; - config_values_t *config; - fifo_buffer_t *audio_fifo; fifo_buffer_t *video_fifo; @@ -138,10 +134,21 @@ typedef struct demux_ogg_s { int send_newpts; int buf_flag_seek; int keyframe_needed; + int ignore_keyframes; } demux_ogg_t ; +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + config_values_t *config; +} demux_ogg_class_t; + static void hex_dump (uint8_t *p, int length) { int i,j; unsigned char c; @@ -170,10 +177,10 @@ static void check_newpts (demux_ogg_t *this, int64_t pts, int video, int preview printf ("demux_ogg: diff=%lld\n", diff); if (this->buf_flag_seek) { - xine_demux_control_newpts(this->xine, pts, BUF_FLAG_SEEK); + xine_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); this->buf_flag_seek = 0; } else { - xine_demux_control_newpts(this->xine, pts, 0); + xine_demux_control_newpts(this->stream, pts, 0); } this->send_newpts = 0; this->last_pts[1-video] = 0; @@ -312,7 +319,7 @@ static void send_ogg_buf (demux_ogg_t *this, } /* - * interpret strea start packages, send headers + * interpret stream start packages, send headers */ static void demux_ogg_send_header (demux_ogg_t *this) { @@ -327,9 +334,11 @@ static void demux_ogg_send_header (demux_ogg_t *this) { ogg_packet op; #ifdef LOG - printf ("demux_ogg: detecting stream types...\n"); + printf ("demux_ogg: detecting stream types...\n"); #endif + this->ignore_keyframes = 0; + while (!done) { int ret = ogg_sync_pageout(&this->oy,&this->og); @@ -395,9 +404,9 @@ static void demux_ogg_send_header (demux_ogg_t *this) { vorbis_comment_init(&vc); if (vorbis_synthesis_headerin(&vi, &vc, &op) >= 0) { - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = vi.bitrate_nominal; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = vi.rate; this->samplerate[stream_num] = vi.rate; @@ -410,7 +419,7 @@ static void demux_ogg_send_header (demux_ogg_t *this) { } else { this->samplerate[stream_num] = 44100; this->preview_buffers[stream_num] = 0; - xine_log (this->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("ogg: vorbis audio track indicated but no vorbis stream header found.\n")); } @@ -469,11 +478,11 @@ static void demux_ogg_send_header (demux_ogg_t *this) { * video metadata */ - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = oggh->hubba.video.width; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = oggh->hubba.video.height; - this->xine->stream_info[XINE_STREAM_INFO_FRAME_DURATION] + this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = this->frame_duration; this->avg_bitrate += 500000; /* FIXME */ @@ -549,13 +558,13 @@ static void demux_ogg_send_header (demux_ogg_t *this) { * audio metadata */ - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = oggh->hubba.audio.channels; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = oggh->bits_per_sample; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = oggh->samples_per_unit; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = oggh->hubba.audio.avgbytespersec*8; } else /* no audio_fifo there */ @@ -624,15 +633,17 @@ static void demux_ogg_send_header (demux_ogg_t *this) { * video metadata */ - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = bih.biWidth; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = bih.biHeight; - this->xine->stream_info[XINE_STREAM_INFO_FRAME_DURATION] + this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = this->frame_duration; this->avg_bitrate += 500000; /* FIXME */ + this->ignore_keyframes = 1; + } else if (*(int32_t*)op.packet+96 == 0x05589F81) { #if 0 @@ -781,16 +792,18 @@ static void demux_ogg_send_content (demux_ogg_t *this) { continue; } - if (this->keyframe_needed) { -// printf ("keyframe needed...\n"); + if (!this->ignore_keyframes && this->keyframe_needed) { +#ifdef LOG + printf ("demux_ogg: keyframe needed... buf_type=%08x\n", this->buf_types[stream_num]); +#endif if (((this->buf_types[stream_num] & 0xFF000000) == BUF_VIDEO_BASE) && (*op.packet == PACKET_IS_SYNCPOINT)) { -/* - printf("keyframe: l%ld b%ld e%ld g%ld p%ld str%d\n", + /* + printf("keyframe: l%ld b%ld e%ld g%ld p%ld str%d\n", op.bytes,op.b_o_s,op.e_o_s,(long) op.granulepos, (long) op.packetno,stream_num); - hex_dump (op.packet, op.bytes); -*/ + hex_dump (op.packet, op.bytes); + */ this->keyframe_needed = 0; } else continue; } @@ -845,7 +858,7 @@ static void *demux_ogg_loop (void *this_gen) { #ifdef LOG printf ("demux_ogg: sending end buffers\n"); #endif - xine_demux_control_end(this->xine, BUF_FLAG_END_STREAM); + xine_demux_control_end(this->stream, BUF_FLAG_END_STREAM); } else { #ifdef LOG printf ("demux_ogg: not sending end buffers\n"); @@ -867,8 +880,10 @@ static void *demux_ogg_loop (void *this_gen) { static void demux_ogg_dispose (demux_plugin_t *this_gen) { demux_ogg_t *this = (demux_ogg_t *) this_gen; + + demux_ogg_stop (this_gen); + free (this); - } static void demux_ogg_stop (demux_plugin_t *this_gen) { @@ -892,9 +907,9 @@ static void demux_ogg_stop (demux_plugin_t *this_gen) { pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - xine_demux_flush_engine(this->xine); + xine_demux_flush_engine(this->stream); - xine_demux_control_end(this->xine, BUF_FLAG_END_USER); + xine_demux_control_end(this->stream, BUF_FLAG_END_USER); } static int demux_ogg_get_status (demux_plugin_t *this_gen) { @@ -903,12 +918,14 @@ static int demux_ogg_get_status (demux_plugin_t *this_gen) { return this->status; } -static int send_headers (demux_ogg_t *this) { +static void demux_ogg_send_headers (demux_plugin_t *this_gen) { + + demux_ogg_t *this = (demux_ogg_t *) this_gen; pthread_mutex_lock( &this->mutex ); - this->video_fifo = this->xine->video_fifo; - this->audio_fifo = this->xine->audio_fifo; + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; this->status = DEMUX_OK; @@ -916,46 +933,38 @@ static int send_headers (demux_ogg_t *this) { * send start buffers */ - if( !this->thread_running ) { -` - this->last_pts[0] = 0; - this->last_pts[1] = 0; + this->last_pts[0] = 0; + this->last_pts[1] = 0; - /* - * initialize ogg engine - */ - ogg_sync_init(&this->oy); - - 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); - } - - if( !this->thread_running && (this->status == DEMUX_OK) ) { - xine_demux_control_start(this->xine); - } else { - xine_demux_flush_engine(this->xine); - } + /* + * initialize ogg engine + */ + ogg_sync_init(&this->oy); + + 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); if (this->status == DEMUX_OK) { + xine_demux_control_start(this->stream); /* send header */ demux_ogg_send_header (this); - xine_demux_control_headers_done (this->xine); - - +#ifdef LOG printf ("demux_ogg: headers sent, avg bitrate is %lld\n", this->avg_bitrate); - - pthread_mutex_unlock (&this->mutex); - return DEMUX_CAN_HANDLE; +#endif } + this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = this->num_video_streams>0; + this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = this->num_audio_streams>0; + + xine_demux_control_headers_done (this->stream); + pthread_mutex_unlock (&this->mutex); - return DEMUX_CANNOT_HANDLE; } static int demux_ogg_start (demux_plugin_t *this_gen, @@ -1010,7 +1019,7 @@ static int demux_ogg_start (demux_plugin_t *this_gen, } } else { this->buf_flag_seek = 1; - xine_demux_flush_engine(this->xine); + xine_demux_flush_engine(this->stream); err = 0; } @@ -1026,126 +1035,145 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, return demux_ogg_start (this_gen, start_pos, start_time); } -static int demux_ogg_open(demux_plugin_t *this_gen, - input_plugin_t *input, int stage) { +static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; + demux_ogg_t *this = (demux_ogg_t *) this_gen; - switch(stage) { + if (this->avg_bitrate) + return this->input->get_length (this->input) * 8 / this->avg_bitrate; + else + return 0; +} - case STAGE_BY_CONTENT: +static demux_plugin_t *open_plugin (demux_class_t *class_gen, + xine_stream_t *stream, + input_plugin_t *input) { + + demux_ogg_t *this; + + switch (stream->content_detection_method) { + + case METHOD_BY_CONTENT: { uint8_t buf[4096]; - if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { + if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { input->seek(input, 0, SEEK_SET); if (input->read(input, buf, 4)) { - if ((buf[0] == 'O') - && (buf[1] == 'g') - && (buf[2] == 'g') - && (buf[3] == 'S')) { - this->input = input; - return send_headers(this); - } - } - } - - if (input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW)) { - if ((buf[0] == 'O') - && (buf[1] == 'g') - && (buf[2] == 'g') - && (buf[3] == 'S')) { - this->input = input; - return send_headers(this); + if ((buf[0] != 'O') + || (buf[1] != 'g') + || (buf[2] != 'g') + || (buf[3] != 'S')) + return NULL; } - } + } else if (input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW)) { + if ((buf[0] != 'O') + || (buf[1] != 'g') + || (buf[2] != 'g') + || (buf[3] != 'S')) + return NULL; + } else + return NULL; } - return DEMUX_CANNOT_HANDLE; break; - case STAGE_BY_EXTENSION: { - char *ending; - char *MRL; - char *m, *valid_ends; + case METHOD_BY_EXTENSION: { + + char *ending, *mrl; - MRL = input->get_mrl (input); + mrl = input->get_mrl (input); /* - * check ending + * check extension */ - ending = strrchr(MRL, '.'); - - if(!ending) - return DEMUX_CANNOT_HANDLE; + ending = strrchr (mrl, '.'); - xine_strdupa(valid_ends, (this->config->register_string(this->config, - "mrl.ends_ogg", VALID_ENDS, - _("valid mrls ending for ogg demuxer"), - NULL, 20, NULL, NULL))); - while((m = xine_strsep(&valid_ends, ",")) != NULL) { + if (!ending) + return NULL; - while(*m == ' ' || *m == '\t') m++; - - if(!strcasecmp((ending + 1), m)) { - this->input = input; - return send_headers(this); - } + if (strncasecmp(ending, ".ogg", 4) && + strncasecmp(ending, ".ogm", 4)) { + return NULL; } + + } break; + default: + return NULL; } - return DEMUX_CANNOT_HANDLE; + /* + * if we reach this point, the input has been accepted. + */ + + this = xine_xmalloc (sizeof (demux_ogg_t)); + this->stream = stream; + this->input = input; + + this->demux_plugin.send_headers = demux_ogg_send_headers; + this->demux_plugin.start = demux_ogg_start; + this->demux_plugin.seek = demux_ogg_seek; + this->demux_plugin.stop = demux_ogg_stop; + this->demux_plugin.dispose = demux_ogg_dispose; + this->demux_plugin.get_status = demux_ogg_get_status; + this->demux_plugin.get_stream_length = demux_ogg_get_stream_length; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + pthread_mutex_init( &this->mutex, NULL ); + + return &this->demux_plugin; } -static char *demux_ogg_get_id(void) { + + +/* + * ogg demuxer class + */ + +static char *get_description (demux_class_t *this_gen) { + return "OGG demux plugin"; +} + +static char *get_identifier (demux_class_t *this_gen) { return "OGG"; } -static char *demux_ogg_get_mimetypes(void) { +static char *get_extensions (demux_class_t *this_gen) { + return "ogg ogm"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-ogg: ogg: OggVorbis Audio;"; } -static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { +static void class_dispose (demux_class_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; + demux_ogg_class_t *this = (demux_ogg_class_t *) this_gen; - if (this->avg_bitrate) - return this->input->get_length (this->input) * 8 / this->avg_bitrate; - else - return 0; + free (this); } -static void *init_demuxer_plugin (xine_t *xine, void *data) { - - demux_ogg_t *this; - - this = xine_xmalloc (sizeof (demux_ogg_t)); +static void *init_class (xine_t *xine, void *data) { + + demux_ogg_class_t *this; + + this = xine_xmalloc (sizeof (demux_ogg_class_t)); this->config = xine->config; this->xine = xine; - (void*) this->config->register_string(this->config, - "mrl.ends_ogg", VALID_ENDS, - _("valid mrls ending for ogg demuxer"), - NULL, 20, NULL, NULL); + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; - this->demux_plugin.open = demux_ogg_open; - this->demux_plugin.start = demux_ogg_start; - this->demux_plugin.seek = demux_ogg_seek; - this->demux_plugin.stop = demux_ogg_stop; - this->demux_plugin.dispose = demux_ogg_dispose; - this->demux_plugin.get_status = demux_ogg_get_status; - this->demux_plugin.get_identifier = demux_ogg_get_id; - this->demux_plugin.get_stream_length = demux_ogg_get_stream_length; - this->demux_plugin.get_mimetypes = demux_ogg_get_mimetypes; - - this->status = DEMUX_FINISHED; - pthread_mutex_init( &this->mutex, NULL ); - return this; } @@ -1155,6 +1183,6 @@ static void *init_demuxer_plugin (xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 11, "ogg", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 14, "ogg", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |