diff options
author | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2007-06-01 21:05:12 +0200 |
---|---|---|
committer | Diego 'Flameeyes' Pettenò <flameeyes@gmail.com> | 2007-06-01 21:05:12 +0200 |
commit | f209e8b8ef44998a5ea20544bbb39aaeefa28086 (patch) | |
tree | 94f304d31e4c4bf3c1f7b0bee11cf8cceb05c15e /src/demuxers/demux_ogg.c | |
parent | 0f8f38c36c4a2c038b11c6c00a477695e0e1908a (diff) | |
download | xine-lib-f209e8b8ef44998a5ea20544bbb39aaeefa28086.tar.gz xine-lib-f209e8b8ef44998a5ea20544bbb39aaeefa28086.tar.bz2 |
Collapse the Ogg demuxer, and the Theora, Vorbis and Speex decoders in the same 'xiph' plugin.
As the three decoders requires Ogg support, and requires an Ogg demuxer to play, enabling any one of them will then enable the ogg demuxer.
The Ogg demuxer, on its own, needs to know which of the three formats are enabled, or it will not be able to properly decode them.
With this change, only one plugin will need to load and know about Xiph formats and libraries.
--HG--
rename : src/demuxers/demux_ogg.c => src/combined/xine_ogg_demuxer.c
rename : src/libxineadec/xine_speex_decoder.c => src/combined/xine_speex_decoder.c
rename : src/libxinevdec/xine_theora_decoder.c => src/combined/xine_theora_decoder.c
rename : src/libxineadec/xine_vorbis_decoder.c => src/combined/xine_vorbis_decoder.c
Diffstat (limited to 'src/demuxers/demux_ogg.c')
-rw-r--r-- | src/demuxers/demux_ogg.c | 2202 |
1 files changed, 0 insertions, 2202 deletions
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c deleted file mode 100644 index f868018af..000000000 --- a/src/demuxers/demux_ogg.c +++ /dev/null @@ -1,2202 +0,0 @@ -/* - * Copyright (C) 2000-2004 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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.177 2007/03/29 19:38:51 dgp85 Exp $ - * - * demultiplexer for ogg streams - * - */ -/* 2003.02.09 (dilb) update of the handling for audio/video infos for strongarm cpus. */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <inttypes.h> - -#include <ogg/ogg.h> -#include <vorbis/codec.h> - -#ifdef HAVE_SPEEX -#include <speex/speex.h> -#include <speex/speex_header.h> -#include <speex/speex_stereo.h> -#include <speex/speex_callbacks.h> -#endif - -#ifdef HAVE_THEORA -#include <theora/theora.h> -#endif - -#define LOG_MODULE "demux_ogg" -#define LOG_VERBOSE - -/* -#define LOG -*/ - -#define DEBUG_PACKETS 0 -#define DEBUG_PREVIEWS 0 -#define DEBUG_PTS 0 -#define DEBUG_VIDEO_PACKETS 0 - -#include "xine_internal.h" -#include "xineutils.h" -#include "demux.h" -#include "bswap.h" -#include "flacutils.h" - -#define CHUNKSIZE 8500 -#define PACKET_TYPE_HEADER 0x01 -#define PACKET_TYPE_COMMENT 0x03 -#define PACKET_TYPE_CODEBOOK 0x05 -#define PACKET_TYPE_BITS 0x07 -#define PACKET_LEN_BITS01 0xc0 -#define PACKET_LEN_BITS2 0x02 -#define PACKET_IS_SYNCPOINT 0x08 - -#define MAX_STREAMS 32 - -#define PTS_AUDIO 0 -#define PTS_VIDEO 1 - -#define WRAP_THRESHOLD 900000 - -#define SUB_BUFSIZE 1024 - -typedef struct chapter_entry_s { - int64_t start_pts; - char *name; -} chapter_entry_t; - -typedef struct chapter_info_s { - int current_chapter; - int max_chapter; - chapter_entry_t *entries; -} chapter_info_t; - -typedef struct stream_info_s { - ogg_stream_state oss; - uint32_t buf_types; - int headers; - int64_t header_granulepos; - int64_t factor; - int64_t quotient; - int resync; - char *language; - /* CMML, Ogg Skeleton stream information */ - int granuleshift; - /* Annodex v2 stream information */ - int hide_first_header; - int delivered_bos; - int delivered_eos; -} stream_info_t; - -typedef struct demux_ogg_s { - demux_plugin_t demux_plugin; - - xine_stream_t *stream; - fifo_buffer_t *audio_fifo; - fifo_buffer_t *video_fifo; - input_plugin_t *input; - int status; - - int frame_duration; - -#ifdef HAVE_THEORA - theora_info t_info; - theora_comment t_comment; -#endif - - ogg_sync_state oy; - ogg_page og; - - int64_t start_pts; - int64_t last_pts[2]; - - int time_length; - - int num_streams; - stream_info_t *si[MAX_STREAMS]; /* stream info */ - - int num_audio_streams; - int num_video_streams; - int unhandled_video_streams; - int num_spu_streams; - - off_t avg_bitrate; - - char *title; - chapter_info_t *chapter_info; - xine_event_queue_t *event_queue; - - uint8_t send_newpts:1; - uint8_t buf_flag_seek:1; - uint8_t keyframe_needed:1; - uint8_t ignore_keyframes:1; -} demux_ogg_t ; - -typedef struct { - demux_class_t demux_class; -} demux_ogg_class_t; - -typedef struct { - demux_class_t demux_class; -} demux_anx_class_t; - - -#ifdef HAVE_THEORA -static int intlog(int num) { - int ret=0; - - while(num>0){ - num=num/2; - ret=ret+1; - } - return(ret); -} -#endif - -static int get_stream (demux_ogg_t *this, int serno) { - /*finds the stream_num, which belongs to a ogg serno*/ - int i; - - for (i = 0; i<this->num_streams; i++) { - if (this->si[i]->oss.serialno == serno) { - return i; - } - } - return -1; -} - -static int new_stream_info (demux_ogg_t *this, const int cur_serno) { - int stream_num; - - this->si[this->num_streams] = (stream_info_t *)xine_xmalloc(sizeof(stream_info_t)); - ogg_stream_init(&this->si[this->num_streams]->oss, cur_serno); - stream_num = this->num_streams; - this->si[stream_num]->buf_types = 0; - this->si[stream_num]->header_granulepos = -1; - this->si[stream_num]->headers = 0; - this->num_streams++; - - return stream_num; -} - -static int64_t get_pts (demux_ogg_t *this, int stream_num , int64_t granulepos ) { - /*calculates an pts from an granulepos*/ - if (granulepos<0) { - if ( this->si[stream_num]->header_granulepos>=0 ) { - /*return the smallest valid pts*/ - return 1; - } else - return 0; - } else if (this->si[stream_num]->buf_types == BUF_VIDEO_THEORA || - (this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_SPU_CMML) { - int64_t iframe, pframe; - int granuleshift; - granuleshift = this->si[stream_num]->granuleshift; - iframe = granulepos >> granuleshift; - pframe = granulepos - (iframe << granuleshift); - if (this->si[stream_num]->quotient) - return 1+((iframe+pframe) * this->si[stream_num]->factor / this->si[stream_num]->quotient); - else - return 0; - } else if (this->si[stream_num]->quotient) - return 1+(granulepos * this->si[stream_num]->factor / this->si[stream_num]->quotient); - else - return 0; -} - -static int read_ogg_packet (demux_ogg_t *this) { - char *buffer; - long bytes; - while (ogg_sync_pageout(&this->oy,&this->og)!=1) { - buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE); - bytes = this->input->read(this->input, buffer, CHUNKSIZE); - ogg_sync_wrote(&this->oy, bytes); - if (bytes < CHUNKSIZE/2) { - return 0; - } - } - return 1; -} - -static void get_stream_length (demux_ogg_t *this) { - /*determine the streamlenght and set this->time_length accordingly. - ATTENTION:current_pos and oggbuffers will be destroyed by this function, - there will be no way to continue playback uninterrupted. - - You have to seek afterwards, because after get_stream_length, the - current_position is at the end of the file */ - - off_t filelength; - int done=0; - int stream_num; - - this->time_length=-1; - - if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { - filelength=this->input->get_length(this->input); - - if (filelength!=-1) { - if (filelength>70000) { - this->demux_plugin.seek(&this->demux_plugin, - (off_t) ( (double)(filelength-65536)/filelength*65535), 0, 0); - } - done=0; - while (!done) { - if (!read_ogg_packet (this)) { - if (this->time_length) { - _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, - ((int64_t) 8000*filelength)/this->time_length); - /*this is a fine place to compute avg_bitrate*/ - this->avg_bitrate= 8000*filelength/this->time_length; - } - return; - } - stream_num=get_stream(this, ogg_page_serialno (&this->og) ); - if (stream_num!=-1) { - if (this->time_length < (get_pts(this, stream_num, ogg_page_granulepos(&this->og) / 90))) - this->time_length = get_pts(this, stream_num, ogg_page_granulepos(&this->og)) / 90; - } - } - } - } -} - -#ifdef HAVE_THEORA -static void send_ogg_packet (demux_ogg_t *this, - fifo_buffer_t *fifo, - ogg_packet *op, - int64_t pts, - uint32_t decoder_flags, - int stream_num) { - - buf_element_t *buf; - - int done=0,todo=op->bytes; - int op_size = sizeof(ogg_packet); - - while (done<todo) { - int offset=0; - buf = fifo->buffer_pool_alloc (fifo); - buf->decoder_flags = decoder_flags; - if (done==0) { - memcpy (buf->content, op, op_size); - offset=op_size; - buf->decoder_flags = buf->decoder_flags | BUF_FLAG_FRAME_START; - } - - if (done+buf->max_size-offset < todo) { - memcpy (buf->content+offset, op->packet+done, buf->max_size-offset); - buf->size = buf->max_size; - done=done+buf->max_size-offset; - } else { - memcpy (buf->content+offset , op->packet+done, todo-done); - buf->size = todo-done+offset; - done=todo; - buf->decoder_flags = buf->decoder_flags | BUF_FLAG_FRAME_END; - } - - buf->pts = pts; - if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * - 65535 / this->input->get_length (this->input) ); - buf->extra_info->input_time = buf->pts / 90 ; - buf->type = this->si[stream_num]->buf_types; - - fifo->put (fifo, buf); - } -} -#endif - -/* redefine abs as macro to handle 64-bit diffs. - i guess llabs may not be available everywhere */ -#define abs(x) ( ((x)<0) ? -(x) : (x) ) - -static void check_newpts (demux_ogg_t *this, int64_t pts, int video, int preview) { - int64_t diff; - - llprintf(DEBUG_PTS, "new pts %" PRId64 " found in stream\n",pts); - - diff = pts - this->last_pts[video]; - - if (!preview && (pts>=0) && - (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) { - - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "diff=%" PRId64 " (pts=%" PRId64 ", last_pts=%" PRId64 ")\n", diff, pts, this->last_pts[video]); - - if (this->buf_flag_seek) { - _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); - this->buf_flag_seek = 0; - } else { - _x_demux_control_newpts(this->stream, pts, 0); - } - this->send_newpts = 0; - this->last_pts[1-video] = 0; - } - - if (!preview && (pts>=0) ) - this->last_pts[video] = pts; - - /* use pts for bitrate measurement */ - - /*compute avg_bitrate if time_length isn't set*/ - if ((pts>180000) && !(this->time_length)) { - this->avg_bitrate = this->input->get_current_pos (this->input) * 8 * 90000/ pts; - - if (this->avg_bitrate<1) - this->avg_bitrate = 1; - - } -} - -static void ogg_handle_event (demux_ogg_t *this) { - xine_event_t *event; - - while ((event = xine_event_get(this->event_queue))) { - switch(event->type) { - case XINE_EVENT_INPUT_NEXT: - { - if (this->chapter_info) { - int c_chap = this->chapter_info->current_chapter; - if (c_chap+1 < this->chapter_info->max_chapter) { - int start_time = this->chapter_info->entries[c_chap+1].start_pts / 90; - this->demux_plugin.seek((demux_plugin_t *)this, 0, start_time, 1); - } - } - } - break; - case XINE_EVENT_INPUT_PREVIOUS: - { - if (this->chapter_info) { - int c_chap = this->chapter_info->current_chapter; - if (c_chap >= 1) { - int start_time = this->chapter_info->entries[c_chap-1].start_pts / 90; - this->demux_plugin.seek((demux_plugin_t *)this, 0, start_time, 1); - } - } - } - break; - } - xine_event_free(event); - } - return; -} - -/* - * utility function to read a LANGUAGE= line from the user_comments, - * to label audio and spu streams - */ -static void read_language_comment (demux_ogg_t *this, ogg_packet *op, int stream_num) { - char **ptr; - char *comment; - vorbis_comment vc; - vorbis_info vi; - - vorbis_comment_init(&vc); - vorbis_info_init(&vi); - - /* this is necessary to make libvorbis accept this vorbis_info*/ - vi.rate=1; - - if ( vorbis_synthesis_headerin(&vi, &vc, op) >= 0) { - ptr=vc.user_comments; - while(*ptr) { - comment=*ptr; - if ( !strncasecmp ("LANGUAGE=", comment, 9) ) { - this->si[stream_num]->language = strdup (comment + strlen ("LANGUAGE=") ); - } - ++ptr; - } - } - vorbis_comment_clear(&vc); - vorbis_info_clear(&vi); -} - -/* - * utility function to read CHAPTER*= and TITLE= from the user_comments, - * to name parts of the videostream - */ -static void read_chapter_comment (demux_ogg_t *this, ogg_packet *op) { - char **ptr; - char *comment; - vorbis_comment vc; - vorbis_info vi; - - vorbis_comment_init(&vc); - vorbis_info_init(&vi); - - /* this is necessary to make libvorbis accept this vorbis_info*/ - vi.rate=1; - - if ( vorbis_synthesis_headerin(&vi, &vc, op) >= 0) { - char *chapter_time = 0; - char *chapter_name = 0; - int chapter_no = 0; - ptr=vc.user_comments; - while(*ptr) { - comment=*ptr; - if ( !strncasecmp ("TITLE=", comment,6) ) { - this->title = strdup (comment + strlen ("TITLE=") ); - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->title); - } - if ( !chapter_time && strlen(comment) == 22 && - !strncasecmp ("CHAPTER" , comment, 7) && - isdigit(*(comment+7)) && isdigit(*(comment+8)) && - (*(comment+9) == '=')) { - - chapter_time = strdup(comment+10); - chapter_no = strtol(comment+7, NULL, 10); - } - if ( !chapter_name && !strncasecmp("CHAPTER", comment, 7) && - isdigit(*(comment+7)) && isdigit(*(comment+8)) && - !strncasecmp ("NAME=", comment+9, 5)) { - - if (strtol(comment+7,NULL,10) == chapter_no) { - chapter_name = strdup(comment+14); - } - } - if (chapter_time && chapter_name && chapter_no){ - int hour, min, sec, msec; - - lprintf("create chapter entry: no=%d name=%s time=%s\n", chapter_no, chapter_name, chapter_time); - hour= strtol(chapter_time, NULL, 10); - min = strtol(chapter_time+3, NULL, 10); - sec = strtol(chapter_time+6, NULL, 10); - msec = strtol(chapter_time+9, NULL, 10); - lprintf("time: %d %d %d %d\n", hour, min,sec,msec); - - if (!this->chapter_info) { - this->chapter_info = (chapter_info_t *)xine_xmalloc(sizeof(chapter_info_t)); - this->chapter_info->current_chapter = -1; - } - this->chapter_info->max_chapter = chapter_no; - this->chapter_info->entries = realloc( this->chapter_info->entries, chapter_no*sizeof(chapter_entry_t)); - this->chapter_info->entries[chapter_no-1].name = chapter_name; - this->chapter_info->entries[chapter_no-1].start_pts = (msec + (1000.0 * sec) + (60000.0 * min) + (3600000.0 * hour))*90; - - free (chapter_time); - chapter_no = 0; - chapter_time = chapter_name = 0; - } - ++ptr; - } - } - vorbis_comment_clear(&vc); - vorbis_info_clear(&vi); -} - -/* - * update the display of the title, if needed - */ -static void update_chapter_display (demux_ogg_t *this, int stream_num, ogg_packet *op) { - int chapter = 0; - int64_t pts = get_pts(this, stream_num, op->granulepos ); - - while (chapter < this->chapter_info->max_chapter && - this->chapter_info->entries[chapter].start_pts < pts) { - chapter++; - } - chapter--; - - if (chapter != this->chapter_info->current_chapter){ - xine_event_t uevent; - xine_ui_data_t data; - int title_len; - char *title; - - this->chapter_info->current_chapter = chapter; - if (chapter >= 0) { - char t_title[256]; - - if (this->title) { - snprintf(t_title, sizeof (t_title), "%s / %s", this->title, this->chapter_info->entries[chapter].name); - } else { - snprintf(t_title, sizeof (t_title), "%s", this->chapter_info->entries[chapter].name); - } - title = t_title; - } else { - title = this->title; - } - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, title); - lprintf("new TITLE: %s\n", title); - - uevent.type = XINE_EVENT_UI_SET_TITLE; - uevent.stream = this->stream; - uevent.data = &data; - uevent.data_length = sizeof(data); - title_len = strlen(title) + 1; - memcpy(data.str, title, title_len); - data.str_len = title_len; - xine_event_send(this->stream, &uevent); - } -} - -/* - * 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) { - - int hdrlen; - int normpos = 0; - - if( this->input->get_length (this->input) ) - normpos = (int)( (double) this->input->get_current_pos (this->input) * - 65535 / this->input->get_length (this->input) ); - - - hdrlen = (*op->packet & PACKET_LEN_BITS01) >> 6; - hdrlen |= (*op->packet & PACKET_LEN_BITS2) << 1; - - /* for Annodex files: the first packet after the AnxData info packet needs - * to have its BOS flag set: we set it here */ - if (!this->si[stream_num]->delivered_bos) { - op->b_o_s = 1; - this->si[stream_num]->delivered_bos = 1; - } - - if ( this->audio_fifo - && (this->si[stream_num]->buf_types & 0xFF000000) == BUF_AUDIO_BASE) { - uint8_t *data; - int size; - int64_t pts; - - if (op->packet[0] == PACKET_TYPE_COMMENT ) { - read_language_comment(this, op, stream_num); - } - - if ((this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_SPEEX || - (this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_FLAC || - (this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_VORBIS) { - data = op->packet; - size = op->bytes; - } else { - data = op->packet+1+hdrlen; - size = op->bytes-1-hdrlen; - } - llprintf(DEBUG_PACKETS, "audio data size %d\n", size); - - if ((op->granulepos != -1) || (this->si[stream_num]->header_granulepos != -1)) { - pts = get_pts(this, stream_num, op->granulepos ); - check_newpts( this, pts, PTS_AUDIO, decoder_flags ); - } else - pts = 0; - - llprintf(DEBUG_PACKETS, - "audiostream %d op-gpos %" PRId64 " hdr-gpos %" PRId64 " pts %" PRId64 " \n", - stream_num, - op->granulepos, - this->si[stream_num]->header_granulepos, - pts); - - _x_demux_send_data(this->audio_fifo, data, size, - pts, this->si[stream_num]->buf_types, decoder_flags, - normpos, - pts / 90, this->time_length, 0); - -#ifdef HAVE_THEORA - } else if ((this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_VIDEO_THEORA) { - - int64_t pts; - theora_info t_info; - theora_comment t_comment; - - theora_info_init (&t_info); - theora_comment_init (&t_comment); - - /*Lets see if this is an Header*/ - if ((theora_decode_header(&t_info, &t_comment, op))>=0) { - decoder_flags=decoder_flags|BUF_FLAG_HEADER; - lprintf ("found an header\n"); - } - - if ((op->granulepos != -1) || (this->si[stream_num]->header_granulepos != -1)) { - pts = get_pts(this, stream_num, op->granulepos ); - check_newpts( this, pts, PTS_VIDEO, decoder_flags ); - } else - pts = 0; - - llprintf(DEBUG_PACKETS, - "theorastream %d op-gpos %" PRId64 " hdr-gpos %" PRId64 " pts %" PRId64 " \n", - stream_num, - op->granulepos, - this->si[stream_num]->header_granulepos, - pts); - - send_ogg_packet (this, this->video_fifo, op, pts, decoder_flags, stream_num); - - theora_comment_clear (&t_comment); - theora_info_clear (&t_info); -#endif - - } else if ((this->si[stream_num]->buf_types & 0xFF000000) == BUF_VIDEO_BASE) { - - uint8_t *data; - int size; - int64_t pts; - - llprintf(DEBUG_VIDEO_PACKETS, - "video buffer, type=%08x\n", this->si[stream_num]->buf_types); - - if (op->packet[0] == PACKET_TYPE_COMMENT ) { - read_chapter_comment(this, op); - }else{ - data = op->packet+1+hdrlen; - size = op->bytes-1-hdrlen; - - if ((op->granulepos != -1) || (this->si[stream_num]->header_granulepos != -1)) { - pts = get_pts(this, stream_num, op->granulepos ); - check_newpts( this, pts, PTS_VIDEO, decoder_flags ); - } else - pts = 0; - - llprintf(DEBUG_VIDEO_PACKETS, - "videostream %d op-gpos %" PRId64 " hdr-gpos %" PRId64 " pts %" PRId64 " \n", - stream_num, - op->granulepos, - this->si[stream_num]->header_granulepos, - pts); - - _x_demux_send_data(this->video_fifo, data, size, - pts, this->si[stream_num]->buf_types, decoder_flags, - normpos, - pts / 90, this->time_length, 0); - - if (this->chapter_info && op->granulepos != -1) { - update_chapter_display(this, stream_num, op); - } - } - } else if ((this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_SPU_CMML) { - buf_element_t *buf; - uint32_t *val; - char *str; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - - buf->type = this->si[stream_num]->buf_types; - - buf->pts = get_pts (this, stream_num, op->granulepos); - - val = (uint32_t * )buf->content; - str = (char *)val; - - memcpy(str, op->packet, op->bytes); - str[op->bytes] = '\0'; - - buf->size = 12 + op->bytes + 1; - - lprintf ("CMML stream %d (bytes=%ld): PTS %"PRId64": %s\n", - stream_num, op->bytes, buf->pts, str); - - this->video_fifo->put (this->video_fifo, buf); - } else if ((this->si[stream_num]->buf_types & 0xFF000000) == BUF_SPU_BASE) { - - buf_element_t *buf; - int i; - char *subtitle,*str; - int lenbytes; - int start,end; - uint32_t *val; - - for (i = 0, lenbytes = 0; i < hdrlen; i++) { - lenbytes = lenbytes << 8; - lenbytes += *((unsigned char *) op->packet + hdrlen - i); - } - - if (op->packet[0] == PACKET_TYPE_HEADER ) { - lprintf ("Textstream-header-packet\n"); - } else if (op->packet[0] == PACKET_TYPE_COMMENT ) { - lprintf ("Textstream-comment-packet\n"); - read_language_comment(this, op, stream_num); - } else { - subtitle = (char *)&op->packet[hdrlen + 1]; - - if ((strlen(subtitle) > 1) || (*subtitle != ' ')) { - start = op->granulepos; - end = start+lenbytes; - lprintf ("subtitlestream %d: %d -> %d :%s\n",stream_num,start,end,subtitle); - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - - buf->type = this->si[stream_num]->buf_types; - buf->pts = 0; - - val = (uint32_t * )buf->content; - *val++ = start; - *val++ = end; - str = (char *)val; - - memcpy (str, subtitle, 1+strlen(subtitle)); - - this->video_fifo->put (this->video_fifo, buf); - } - } - } else { - lprintf("unknown stream type %x\n", this->si[stream_num]->buf_types); - } -} - -static void decode_vorbis_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - vorbis_info vi; - vorbis_comment vc; - - this->si[stream_num]->buf_types = BUF_AUDIO_VORBIS - +this->num_audio_streams++; - - this->si[stream_num]->headers = 3; - - vorbis_info_init(&vi); - vorbis_comment_init(&vc); - if (vorbis_synthesis_headerin(&vi, &vc, op) >= 0) { - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, vi.bitrate_nominal); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, vi.rate); - - this->si[stream_num]->factor = 90000; - this->si[stream_num]->quotient = vi.rate; - - if (vi.bitrate_nominal<1) - this->avg_bitrate += 100000; /* assume 100 kbit */ - else - this->avg_bitrate += vi.bitrate_nominal; - - } else { - this->si[stream_num]->factor = 900; - this->si[stream_num]->quotient = 441; - - this->si[stream_num]->headers = 0; - xine_log (this->stream->xine, XINE_LOG_MSG, - _("ogg: vorbis audio track indicated but no vorbis stream header found.\n")); - } - vorbis_comment_clear(&vc); - vorbis_info_clear(&vi); -} - -static void decode_speex_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { -#ifdef HAVE_SPEEX - void *st; - SpeexMode *mode; - SpeexHeader *header; - - this->si[stream_num]->buf_types = BUF_AUDIO_SPEEX - +this->num_audio_streams++; - - this->si[stream_num]->headers = 1; - - header = speex_packet_to_header (op->packet, op->bytes); - - if (header) { - int bitrate; - mode = (SpeexMode *) speex_mode_list[header->mode]; - - st = speex_decoder_init (mode); - - speex_decoder_ctl (st, SPEEX_GET_BITRATE, &bitrate); - - if (bitrate <= 1) - bitrate = 16000; /* assume 16 kbit */ - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, bitrate); - - this->si[stream_num]->factor = 90000; - this->si[stream_num]->quotient = header->rate; - - this->avg_bitrate += bitrate; - - lprintf ("detected Speex stream,\trate %d\tbitrate %d\n", header->rate, bitrate); - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, header->rate); - this->si[stream_num]->headers += header->extra_headers; - } -#else - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Speex stream detected, unable to play\n"); - - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; -#endif -} - -static void decode_video_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - buf_element_t *buf; - xine_bmiheader bih; - int channel; - - int16_t locbits_per_sample; - uint32_t locsubtype; - int32_t locsize, locdefault_len, locbuffersize, locwidth, locheight; - int64_t loctime_unit, locsamples_per_unit; - - /* read fourcc with machine endianness */ - locsubtype = *((uint32_t *)&op->packet[9]); - - /* everything else little endian */ - locsize = LE_32(&op->packet[13]); - loctime_unit = LE_64(&op->packet[17]); - locsamples_per_unit = LE_64(&op->packet[25]); - locdefault_len = LE_32(&op->packet[33]); - locbuffersize = LE_32(&op->packet[37]); - locbits_per_sample = LE_16(&op->packet[41]); - locwidth = LE_32(&op->packet[45]); - locheight = LE_32(&op->packet[49]); - - lprintf ("direct show filter created stream detected, hexdump:\n"); -#ifdef LOG - xine_hexdump (op->packet, op->bytes); -#endif - - channel = this->num_video_streams++; - - this->si[stream_num]->buf_types = _x_fourcc_to_buf_video (locsubtype); - if( !this->si[stream_num]->buf_types ) - this->si[stream_num]->buf_types = BUF_VIDEO_UNKNOWN; - this->si[stream_num]->buf_types |= channel; - this->si[stream_num]->headers = 0; /* header is sent below */ - - lprintf ("subtype %.4s\n", (char*)&locsubtype); - lprintf ("time_unit %" PRId64 "\n", loctime_unit); - lprintf ("samples_per_unit %" PRId64 "\n", locsamples_per_unit); - lprintf ("default_len %d\n", locdefault_len); - lprintf ("buffersize %d\n", locbuffersize); - lprintf ("bits_per_sample %d\n", locbits_per_sample); - lprintf ("width %d\n", locwidth); - lprintf ("height %d\n", locheight); - lprintf ("buf_type %08x\n",this->si[stream_num]->buf_types); - - bih.biSize=sizeof(xine_bmiheader); - bih.biWidth = locwidth; - bih.biHeight= locheight; - bih.biPlanes= 0; - memcpy(&bih.biCompression, &locsubtype, 4); - bih.biBitCount= 0; - bih.biSizeImage=locwidth*locheight; - bih.biXPelsPerMeter=1; - bih.biYPelsPerMeter=1; - bih.biClrUsed=0; - bih.biClrImportant=0; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE| - BUF_FLAG_FRAME_END; - this->frame_duration = loctime_unit * 9 / 1000; - this->si[stream_num]->factor = loctime_unit * 9; - this->si[stream_num]->quotient = 1000; - buf->decoder_info[0] = this->frame_duration; - memcpy (buf->content, &bih, sizeof (xine_bmiheader)); - buf->size = sizeof (xine_bmiheader); - buf->type = this->si[stream_num]->buf_types; - - /* video metadata */ - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC, locsubtype); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, locwidth); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, locheight); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->frame_duration); - - this->avg_bitrate += 500000; /* FIXME */ - - this->video_fifo->put (this->video_fifo, buf); -} - -static void decode_audio_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - - if (this->audio_fifo) { - buf_element_t *buf; - int codec; - char str[5]; - int channel; - - int16_t locbits_per_sample, locchannels, locblockalign; - int32_t locsize, locdefault_len, locbuffersize, locavgbytespersec; - int64_t loctime_unit, locsamples_per_unit; - - locsize = LE_32(&op->packet[13]); - loctime_unit = LE_64(&op->packet[17]); - locsamples_per_unit = LE_64(&op->packet[25]); - locdefault_len = LE_32(&op->packet[33]); - locbuffersize = LE_32(&op->packet[37]); - locbits_per_sample = LE_16(&op->packet[41]); - locchannels = LE_16(&op->packet[45]); - locblockalign = LE_16(&op->packet[47]); - locavgbytespersec= LE_32(&op->packet[49]); - - lprintf ("direct show filter created audio stream detected, hexdump:\n"); -#ifdef LOG - xine_hexdump (op->packet, op->bytes); -#endif - - memcpy(str, &op->packet[9], 4); - str[4] = 0; - codec = strtoul(str, NULL, 16); - - channel= this->num_audio_streams++; - - this->si[stream_num]->buf_types = _x_formattag_to_buf_audio(codec); - if( this->si[stream_num]->buf_types ) { - this->si[stream_num]->buf_types |= channel; - } else { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_ogg: unknown audio codec type 0x%x\n", codec); - this->si[stream_num]->buf_types = BUF_AUDIO_UNKNOWN; - /*break;*/ - } - - lprintf ("subtype 0x%x\n", codec); - lprintf ("time_unit %" PRId64 "\n", loctime_unit); - lprintf ("samples_per_unit %" PRId64 "\n", locsamples_per_unit); - lprintf ("default_len %d\n", locdefault_len); - lprintf ("buffersize %d\n", locbuffersize); - lprintf ("bits_per_sample %d\n", locbits_per_sample); - lprintf ("channels %d\n", locchannels); - lprintf ("blockalign %d\n", locblockalign); - lprintf ("avgbytespersec %d\n", locavgbytespersec); - lprintf ("buf_type %08x\n",this->si[stream_num]->buf_types); - - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = this->si[stream_num]->buf_types; - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - buf->decoder_info[0] = 0; - buf->decoder_info[1] = locsamples_per_unit; - buf->decoder_info[2] = locbits_per_sample; - buf->decoder_info[3] = locchannels; - this->audio_fifo->put (this->audio_fifo, buf); - - this->si[stream_num]->headers = 0; /* header already sent */ - this->si[stream_num]->factor = 90000; - this->si[stream_num]->quotient = locsamples_per_unit; - - this->avg_bitrate += locavgbytespersec*8; - - /* audio metadata */ - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, codec); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, locchannels); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, locbits_per_sample); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, locsamples_per_unit); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, locavgbytespersec * 8); - - } else /* no audio_fifo there */ - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; -} - -static void decode_dshow_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - - lprintf ("older Direct Show filter-generated stream header detected. Hexdump:\n"); -#ifdef LOG - xine_hexdump (op->packet, op->bytes); -#endif - - this->si[stream_num]->headers = 0; /* header is sent below */ - - if ( (LE_32(&op->packet[96]) == 0x05589f80) && (op->bytes >= 184)) { - - buf_element_t *buf; - xine_bmiheader bih; - int channel; - uint32_t fcc; - - lprintf ("seems to be a video stream.\n"); - - channel = this->num_video_streams++; - fcc = *(uint32_t*)(op->packet+68); - lprintf ("fourcc %08x\n", fcc); - - this->si[stream_num]->buf_types = _x_fourcc_to_buf_video (fcc); - if( !this->si[stream_num]->buf_types ) - this->si[stream_num]->buf_types = BUF_VIDEO_UNKNOWN; - this->si[stream_num]->buf_types |= channel; - - bih.biSize = sizeof(xine_bmiheader); - bih.biWidth = LE_32(&op->packet[176]); - bih.biHeight = LE_32(&op->packet[180]); - bih.biPlanes = 0; - memcpy (&bih.biCompression, op->packet+68, 4); - bih.biBitCount = LE_16(&op->packet[182]); - if (!bih.biBitCount) - bih.biBitCount = 24; /* FIXME ? */ - bih.biSizeImage = (bih.biBitCount>>3)*bih.biWidth*bih.biHeight; - bih.biXPelsPerMeter = 1; - bih.biYPelsPerMeter = 1; - bih.biClrUsed = 0; - bih.biClrImportant = 0; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE| - BUF_FLAG_FRAME_END; - this->frame_duration = (*(int64_t*)(op->packet+164)) * 9 / 1000; - this->si[stream_num]->factor = (*(int64_t*)(op->packet+164)) * 9; - this->si[stream_num]->quotient = 1000; - - buf->decoder_info[0] = this->frame_duration; - memcpy (buf->content, &bih, sizeof (xine_bmiheader)); - buf->size = sizeof (xine_bmiheader); - buf->type = this->si[stream_num]->buf_types; - this->video_fifo->put (this->video_fifo, buf); - - lprintf ("subtype %.4s\n", (char*)&fcc); - lprintf ("buf_type %08x\n", this->si[stream_num]->buf_types); - lprintf ("video size %d x %d\n", bih.biWidth, bih.biHeight); - lprintf ("frame duration %d\n", this->frame_duration); - - /* video metadata */ - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, bih.biWidth); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, bih.biHeight); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->frame_duration); - - this->avg_bitrate += 500000; /* FIXME */ - - this->ignore_keyframes = 1; - - } else if (LE_32(&op->packet[96]) == 0x05589F81) { - -#if 0 - /* FIXME: no test streams */ - - buf_element_t *buf; - int codec; - char str[5]; - int channel; - int extra_size; - - extra_size = *(int16_t*)(op->packet+140); - format = *(int16_t*)(op->packet+124); - channels = *(int16_t*)(op->packet+126); - samplerate = *(int32_t*)(op->packet+128); - nAvgBytesPerSec = *(int32_t*)(op->packet+132); - nBlockAlign = *(int16_t*)(op->packet+136); - wBitsPerSample = *(int16_t*)(op->packet+138); - samplesize = (sh_a->wf->wBitsPerSample+7)/8; - cbSize = extra_size; - if(extra_size > 0) - memcpy(wf+sizeof(WAVEFORMATEX),op->packet+142,extra_size); -#endif - - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "FIXME, old audio format not handled\n"); - - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - - } else { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "old header detected but stream type is unknown\n"); - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - } -} - -static void decode_text_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - int channel=0; - uint32_t *val; - buf_element_t *buf; - - lprintf ("textstream detected.\n"); - this->si[stream_num]->headers = 2; - channel = this->num_spu_streams++; - this->si[stream_num]->buf_types = BUF_SPU_OGM | channel; - - /*send an empty spu to inform the video_decoder, that there is a stream*/ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = this->si[stream_num]->buf_types; - buf->pts = 0; - val = (uint32_t * )buf->content; - *val++=0; - *val++=0; - *val++=0; - this->video_fifo->put (this->video_fifo, buf); -} - -static void decode_theora_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - -#ifdef HAVE_THEORA - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_ogg: Theorastreamsupport is highly alpha at the moment\n"); - - if (theora_decode_header(&this->t_info, &this->t_comment, op) >= 0) { - - this->num_video_streams++; - - this->si[stream_num]->factor = (int64_t) 90000 * (int64_t) this->t_info.fps_denominator; - - if (!this->t_info.fps_numerator) { - this->t_info.fps_numerator = 1; /* FIXME: default value ? */ - } - this->si[stream_num]->quotient = this->t_info.fps_numerator; - - this->frame_duration = ((int64_t) 90000*this->t_info.fps_denominator); - this->frame_duration /= this->t_info.fps_numerator; - - this->si[stream_num]->granuleshift = intlog(this->t_info.keyframe_frequency_force-1); - - this->si[stream_num]->headers=3; - this->si[stream_num]->buf_types = BUF_VIDEO_THEORA; - - _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, "theora"); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->t_info.frame_width); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->t_info.frame_height); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->frame_duration); - - /*currently aspect_nominator and -denumerator are 0?*/ - if (this->t_info.aspect_denominator) { - int64_t ratio = ((int64_t) this->t_info.aspect_numerator * 10000); - - ratio /= this->t_info.aspect_denominator; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ratio); - } - - lprintf ("decoded theora header \n"); - lprintf ("frameduration %d\n",this->frame_duration); - lprintf ("w:%d h:%d \n",this->t_info.frame_width,this->t_info.frame_height); - lprintf ("an:%d ad:%d \n",this->t_info.aspect_numerator,this->t_info.aspect_denominator); - } else { - /*Rejected stream*/ - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "A theora header was rejected by libtheora\n"); - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - this->si[stream_num]->headers = 0; /* FIXME: don't know */ - } -#else - this->si[stream_num]->buf_types = BUF_VIDEO_THEORA; - this->num_video_streams++; - this->unhandled_video_streams++; - _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, "theora"); -#endif -} - -static void decode_flac_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - xine_flac_metadata_header header; - xine_flac_streaminfo_block streaminfo; - buf_element_t *buf; - xine_waveformatex wave; - - /* Packet type */ - _x_assert(op->packet[0] == 0x7F); - - /* OggFLAC signature */ - _x_assert(op->packet[1] == 'F'); _x_assert(op->packet[2] == 'L'); - _x_assert(op->packet[3] == 'A'); _x_assert(op->packet[4] == 'C'); - - /* Version: supported only 1.0 */ - _x_assert(op->packet[5] == 1); _x_assert(op->packet[6] == 0); - - /* Header count */ - this->si[stream_num]->headers = 0/*BE_16(&op->packet[7]) +1*/; - - /* fLaC signature */ - _x_assert(op->packet[9] == 'f'); _x_assert(op->packet[10] == 'L'); - _x_assert(op->packet[11] == 'a'); _x_assert(op->packet[12] == 'C'); - - _x_parse_flac_metadata_header(&op->packet[13], &header); - - switch ( header.blocktype ) { - case FLAC_BLOCKTYPE_STREAMINFO: - _x_assert(header.length == FLAC_STREAMINFO_SIZE); - _x_parse_flac_streaminfo_block(&op->packet[17], &streaminfo); - break; - } - - this->si[stream_num]->buf_types = BUF_AUDIO_FLAC - +this->num_audio_streams++; - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, streaminfo.samplerate); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, streaminfo.channels); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, streaminfo.bits_per_sample); - - this->si[stream_num]->factor = 90000; - - buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); - - buf->type = BUF_AUDIO_FLAC; - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - - buf->decoder_info[0] = 0; - buf->decoder_info[1] = streaminfo.samplerate; - buf->decoder_info[2] = streaminfo.bits_per_sample; - buf->decoder_info[3] = streaminfo.channels; - buf->size = sizeof(xine_waveformatex) + FLAC_STREAMINFO_SIZE; - memcpy(buf->content+sizeof(xine_waveformatex), &op->packet[17], FLAC_STREAMINFO_SIZE); - xine_hexdump(&op->packet[17], FLAC_STREAMINFO_SIZE); - wave.cbSize = FLAC_STREAMINFO_SIZE; - memcpy(buf->content, &wave, sizeof(xine_waveformatex)); - - this->audio_fifo->put(this->audio_fifo, buf); - - /* Skip the Ogg framing info */ - op->bytes -= 9; - op->packet += 9; -} - -static void decode_annodex_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - lprintf ("Annodex stream detected\n"); - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - this->si[stream_num]->headers = 1; - this->si[stream_num]->header_granulepos = op->granulepos; - _x_meta_info_set(this->stream, XINE_META_INFO_SYSTEMLAYER, "Annodex"); -} - -static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - int64_t granule_rate_n, granule_rate_d; - uint32_t secondary_headers; - char content_type[1024]; - int content_type_length; - - lprintf("AnxData stream detected\n"); - - /* read granule rate */ - granule_rate_n = LE_64(&op->packet[8]); - granule_rate_d = LE_64(&op->packet[16]); - secondary_headers = LE_32(&op->packet[24]); - - lprintf("granule_rate %" PRId64 "/%" PRId64 ", %d secondary headers\n", - granule_rate_n, granule_rate_d, secondary_headers); - - /* read "Content-Tyoe" MIME header */ - sscanf(&op->packet[28], "Content-Type: %1023s\r\n", content_type); - content_type_length = strlen(content_type); - - lprintf("Content-Type: %s (length:%d)\n", content_type, content_type_length); - - /* how many header packets in the AnxData stream? */ - this->si[stream_num]->headers = secondary_headers + 1; - this->si[stream_num]->hide_first_header = 1; - - /* set factor and quotient */ - this->si[stream_num]->factor = (int64_t) 90000 * granule_rate_d; - this->si[stream_num]->quotient = granule_rate_n; - - lprintf("factor: %" PRId64 ", quotient: %" PRId64 "\n", - this->si[stream_num]->factor, this->si[stream_num]->quotient); - - /* what type of stream are we dealing with? */ - if (!strncmp(content_type, "audio/x-vorbis", content_type_length)) { - this->si[stream_num]->buf_types = BUF_AUDIO_VORBIS; - this->num_audio_streams++; - } else if (!strncmp(content_type, "audio/x-speex", content_type_length)) { - this->num_audio_streams++; -#ifdef HAVE_SPEEX - this->si[stream_num]->buf_types = BUF_AUDIO_SPEEX; -#else - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; -#endif - } else if (!strncmp(content_type, "video/x-theora", content_type_length)) { - this->num_video_streams++; -#ifdef HAVE_THEORA - this->si[stream_num]->buf_types = BUF_VIDEO_THEORA; -#else - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; -#endif - } else if (!strncmp(content_type, "text/x-cmml", content_type_length)) { - unsigned int channel = this->num_spu_streams++; - this->si[stream_num]->headers = 0; - this->si[stream_num]->buf_types = BUF_SPU_CMML | channel; - this->si[stream_num]->granuleshift = 0; - } else { - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - } - -} - -static void decode_cmml_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { - unsigned int channel = this->num_spu_streams++; - this->si[stream_num]->headers = 0; - this->si[stream_num]->buf_types = BUF_SPU_CMML | channel; - - this->si[stream_num]->factor = 90000 * LE_64(&op->packet[20]); - this->si[stream_num]->quotient = LE_64(&op->packet[12]); - this->si[stream_num]->granuleshift = (int)op->packet[28]; -} - -/* - * interpret stream start packages, send headers - */ -static void send_header (demux_ogg_t *this) { - - int stream_num = -1; - int cur_serno; - int done = 0; - ogg_packet op; - xine_event_t ui_event; - - lprintf ("detecting stream types...\n"); - - this->ignore_keyframes = 0; - - while (!done) { - if (!read_ogg_packet(this)) { - this->status = DEMUX_FINISHED; - return; - } - /* now we've got at least one new page */ - - cur_serno = ogg_page_serialno (&this->og); - - if (ogg_page_bos(&this->og)) { - lprintf ("beginning of stream\n"); - lprintf ("serial number %d\n", cur_serno); - - if( this->num_streams == MAX_STREAMS ) { - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "demux_ogg: MAX_STREAMS exceeded, aborting.\n"); - this->status = DEMUX_FINISHED; - return; - } - stream_num = new_stream_info(this, cur_serno); - - } else { - stream_num = get_stream(this, cur_serno); - if (stream_num == -1) { - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "demux_ogg: stream with no beginning!\n"); - this->status = DEMUX_FINISHED; - return; - } - } - - ogg_stream_pagein(&this->si[stream_num]->oss, &this->og); - - while (ogg_stream_packetout(&this->si[stream_num]->oss, &op) == 1) { - - if (!this->si[stream_num]->buf_types) { - - /* detect buftype */ - if (!strncmp (&op.packet[1], "vorbis", 6)) { - decode_vorbis_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[0], "Speex", 5)) { - decode_speex_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[1], "video", 5)) { - decode_video_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[1], "audio", 5)) { - decode_audio_header(this, stream_num, &op); - } else if (op.bytes >= 142 - && !strncmp (&op.packet[1], "Direct Show Samples embedded in Ogg", 35) ) { - decode_dshow_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[1], "text", 4)) { - decode_text_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[1], "theora", 6)) { - decode_theora_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[1], "FLAC", 4)) { - decode_flac_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[0], "Annodex", 7)) { - decode_annodex_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[0], "AnxData", 7)) { - decode_anxdata_header(this, stream_num, &op); - } else if (!strncmp (&op.packet[0], "CMML", 4)) { - decode_cmml_header(this, stream_num, &op); - } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_ogg: unknown stream type (signature >%.8s<). hex dump of bos packet follows:\n", - op.packet); - if(this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG) - xine_hexdump (op.packet, op.bytes); - - this->si[stream_num]->buf_types = BUF_CONTROL_NOP; - } - } - - /* send preview buffer */ - if (this->si[stream_num]->headers > 0 || - op.packet[0] == PACKET_TYPE_COMMENT) { - if (this->si[stream_num]->hide_first_header) - this->si[stream_num]->hide_first_header = 0; - else { - lprintf ("sending preview buffer of stream type %08x\n", - this->si[stream_num]->buf_types); - - send_ogg_buf (this, &op, stream_num, BUF_FLAG_HEADER); - this->si[stream_num]->headers --; - } - } - - /* are we finished ? */ - if (!ogg_page_bos(&this->og)) { - int i; - done = 1; - - for (i=0; i<this->num_streams; i++) { - if (this->si[i]->headers > 0) - done = 0; - - llprintf(DEBUG_PREVIEWS, - "%d preview buffers left to send from stream %d\n", - this->si[i]->headers, i); - } - } - } - } - - ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; - ui_event.data_length = 0; - xine_event_send(this->stream, &ui_event); - - /*get the streamlength*/ - get_stream_length (this); - -} - -static int demux_ogg_send_chunk (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; - - int stream_num; - int cur_serno; - - ogg_packet op; - - ogg_handle_event(this); - - llprintf(DEBUG_PACKETS, "send package...\n"); - - if (!read_ogg_packet(this)) { - this->status = DEMUX_FINISHED; - lprintf ("EOF\n"); - return this->status; - } - - /* now we've got one new page */ - - cur_serno = ogg_page_serialno (&this->og); - stream_num = get_stream(this, cur_serno); - if (stream_num < 0) { - lprintf ("error: unknown stream, serialnumber %d\n", cur_serno); - - if (!ogg_page_bos(&this->og)) { - lprintf ("help, stream with no beginning!\n"); - } - lprintf ("adding late stream with serial number %d (all content will be discarded)\n", cur_serno); - - if( this->num_streams == MAX_STREAMS ) { - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "demux_ogg: MAX_STREAMS exceeded, aborting.\n"); - this->status = DEMUX_FINISHED; - return this->status; - } - stream_num = new_stream_info(this, cur_serno); - } - - ogg_stream_pagein(&this->si[stream_num]->oss, &this->og); - - if (ogg_page_bos(&this->og)) { - lprintf ("beginning of stream: serial number %d - discard\n", - ogg_page_serialno (&this->og)); - while (ogg_stream_packetout(&this->si[stream_num]->oss, &op) == 1) ; - return this->status; - } - - /*while keyframeseeking only process videostream*/ - if (!this->ignore_keyframes && this->keyframe_needed - && ((this->si[stream_num]->buf_types & 0xFF000000) != BUF_VIDEO_BASE)) - return this->status; - - while (ogg_stream_packetout(&this->si[stream_num]->oss, &op) == 1) { - /* printf("demux_ogg: packet: %.8s\n", op.packet); */ - /* printf("demux_ogg: got a packet\n"); */ - - if ((*op.packet & PACKET_TYPE_HEADER) && - (this->si[stream_num]->buf_types!=BUF_VIDEO_THEORA) && (this->si[stream_num]->buf_types!=BUF_AUDIO_SPEEX) && (this->si[stream_num]->buf_types!=BUF_AUDIO_FLAC)) { - if (op.granulepos != -1) { - this->si[stream_num]->header_granulepos = op.granulepos; - lprintf ("header with granulepos, remembering granulepos\n"); - } else { - lprintf ("header => discard\n"); - } - continue; - } - - /*discard granulepos-less packets and to early audiopackets*/ - if (this->si[stream_num]->resync) { - if ((this->si[stream_num]->buf_types & 0xFF000000) == BUF_SPU_BASE) { - /*never drop subtitles*/ - this->si[stream_num]->resync=0; - } else if ((op.granulepos == -1) && (this->si[stream_num]->header_granulepos == -1)) { - continue; - } else { - - /*dump too early packets*/ - if ((get_pts(this,stream_num,op.granulepos)-this->start_pts) > -90000) - this->si[stream_num]->resync=0; - else - continue; - } - } - - if (!this->ignore_keyframes && this->keyframe_needed) { - lprintf ("keyframe needed... buf_type=%08x\n", this->si[stream_num]->buf_types); - if (this->si[stream_num]->buf_types == BUF_VIDEO_THEORA) { -#ifdef HAVE_THEORA - - int keyframe_granule_shift; - int64_t pframe=-1,iframe=-1; - - keyframe_granule_shift = this->si[stream_num]->granuleshift; - - if(op.granulepos>=0){ - iframe=op.granulepos>>keyframe_granule_shift; - pframe=op.granulepos-(iframe<<keyframe_granule_shift); - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "seeking keyframe i %" PRId64 " p %" PRId64 "\n", iframe, pframe); - if (pframe!=0) - continue; - } else - continue; - this->keyframe_needed = 0; - this->start_pts=get_pts(this,stream_num,op.granulepos); -#endif - } else if ((this->si[stream_num]->buf_types & 0xFF000000) == BUF_VIDEO_BASE) { - - /*calculate the current pts*/ - if (op.granulepos!=-1) { - this->start_pts=get_pts(this, stream_num, op.granulepos); - } else if (this->start_pts!=-1) - this->start_pts=this->start_pts+this->frame_duration; - - /*seek the keyframe*/ - if ((*op.packet == PACKET_IS_SYNCPOINT) && (this->start_pts!=-1)) - this->keyframe_needed = 0; - else - continue; - - } else if ((this->si[stream_num]->buf_types & 0xFF000000) == BUF_VIDEO_BASE) continue; - } - send_ogg_buf (this, &op, stream_num, 0); - - /*delete used header_granulepos*/ - if (op.granulepos == -1) - this->si[stream_num]->header_granulepos = -1; - - } - if (ogg_page_eos(&this->og)) { - int i; - int finished_streams = 0; - - lprintf("end of stream, serialnumber %d\n", cur_serno); - this->si[stream_num]->delivered_eos = 1; - - /* check if all logical streams are finished */ - for (i = 0; i < this->num_streams; i++) { - finished_streams += this->si[i]->delivered_eos; - } - - /* if all streams are finished, perhaps a chained stream follows */ - if (finished_streams == this->num_streams) { - /* delete current logical streams */ - for (i = 0; i < this->num_streams; i++) { - ogg_stream_clear(&this->si[i]->oss); - if (this->si[i]->language) { - free (this->si[i]->language); - } - free (this->si[i]); - } - this->num_streams = 0; - this->num_audio_streams = 0; - this->num_video_streams = 0; - this->unhandled_video_streams = 0; - this->num_spu_streams = 0; - this->avg_bitrate = 1; - - /* try to read a chained stream */ - this->send_newpts = 1; - this->last_pts[0] = 0; - this->last_pts[1] = 0; - - /* send control buffer to avoid buffer leak */ - _x_demux_control_end(this->stream, 0); - _x_demux_control_start(this->stream); - send_header(this); - } - } - - return this->status; -} - -static void demux_ogg_dispose (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; - int i; - - for (i=0; i<this->num_streams; i++) { - ogg_stream_clear(&this->si[i]->oss); - - if (this->si[i]->language) { - free (this->si[i]->language); - } - free(this->si[i]); - } - - ogg_sync_clear(&this->oy); - -#ifdef HAVE_THEORA - theora_comment_clear (&this->t_comment); - theora_info_clear (&this->t_info); -#endif - - if (this->chapter_info){ - free (this->chapter_info->entries); - free (this->chapter_info); - } - if (this->title){ - free (this->title); - } - if (this->event_queue) - xine_event_dispose_queue (this->event_queue); - - free (this); -} - -static int demux_ogg_get_status (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; - - return this->status; -} - -static void demux_ogg_send_headers (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; - - this->video_fifo = this->stream->video_fifo; - this->audio_fifo = this->stream->audio_fifo; - - this->status = DEMUX_OK; - - /* - * send start buffers - */ - - 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->num_spu_streams = 0; - this->avg_bitrate = 1; - - this->input->seek (this->input, 0, SEEK_SET); - - if (this->status == DEMUX_OK) { - _x_demux_control_start(this->stream); - send_header (this); - lprintf ("headers sent, avg bitrate is %" PRId64 "\n", this->avg_bitrate); - } - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, - this->num_video_streams > 0); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, - this->num_video_streams > this->unhandled_video_streams); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, - this->num_audio_streams > 0); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL, - this->num_spu_streams); -} - -static int demux_ogg_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time, int playing) { - - demux_ogg_t *this = (demux_ogg_t *) this_gen; - int i; - start_time /= 1000; - start_pos = (off_t) ( (double) start_pos / 65535 * - this->input->get_length (this->input) ); - /* - * seek to start position - */ - - if (INPUT_IS_SEEKABLE(this->input)) { - - this->keyframe_needed = (this->num_video_streams>0); - - if ( (!start_pos) && (start_time)) { - if (this->time_length != -1) { - /*do the seek via time*/ - int current_time=-1; - off_t current_pos; - current_pos=this->input->get_current_pos(this->input); - - /*try to find out the current time*/ - if (this->last_pts[PTS_VIDEO]) { - current_time=this->last_pts[PTS_VIDEO]/90000; - } else if (this->last_pts[PTS_AUDIO]) { - current_time=this->last_pts[PTS_AUDIO]/90000; - } - - /*fixme, the file could grow, do something - about this->time_length using get_lenght to verify, that the stream - hasn` changed its length, otherwise no seek to "new" data is possible*/ - - lprintf ("seek to time %d called\n",start_time); - lprintf ("current time is %d\n",current_time); - - if (current_time > start_time) { - /*seek between beginning and current_pos*/ - - /*fixme - sometimes we seek backwards and during - keyframeseeking, we undo the seek*/ - - start_pos = start_time * current_pos - / current_time ; - } else { - /*seek between current_pos and end*/ - start_pos = current_pos + - ((start_time - current_time) * - ( this->input->get_length(this->input) - current_pos ) / - ( (this->time_length / 1000) - current_time) - ); - } - - lprintf ("current_pos is %" PRId64 "\n",current_pos); - lprintf ("new_pos is %" PRId64 "\n",start_pos); - - } else { - /*seek using avg_bitrate*/ - start_pos = start_time * this->avg_bitrate/8; - } - - lprintf ("seeking to %d seconds => %" PRId64 " bytes\n", - start_time, start_pos); - - } - - ogg_sync_reset(&this->oy); - - for (i=0; i<this->num_streams; i++) { - this->si[i]->header_granulepos = -1; - ogg_stream_reset(&this->si[i]->oss); - } - - /*some strange streams have no syncpoint flag set at the beginning*/ - if (start_pos == 0) - this->keyframe_needed = 0; - - lprintf ("seek to %" PRId64 " called\n",start_pos); - - this->input->seek (this->input, start_pos, SEEK_SET); - - } - - /* fixme - this would be a nice position to do the following tasks - 1. adjust an ogg videostream to a keyframe - 2. compare the keyframe_pts with start_time. if the difference is to - high (e.g. larger than max keyframe_intervall, do a new seek or - continue reading - 3. adjust the audiostreams in such a way, that the - difference is not to high. - - In short words, do all the cleanups necessary to continue playback - without further actions - */ - - this->send_newpts = 1; - this->status = DEMUX_OK; - - if( !playing ) { - - this->buf_flag_seek = 0; - - } else { - if (start_pos!=0) { - this->buf_flag_seek = 1; - /*each stream has to continue with a packet that has an - granulepos*/ - for (i=0; i<this->num_streams; i++) { - this->si[i]->resync = 1; - } - - this->start_pts=-1; - } - - _x_demux_flush_engine(this->stream); - } - - return this->status; -} - -static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { - - demux_ogg_t *this = (demux_ogg_t *) this_gen; - - if (this->time_length==-1){ - if (this->avg_bitrate) { - return (int)((int64_t)1000 * this->input->get_length (this->input) * 8 / - this->avg_bitrate); - } else { - return 0; - } - } else { - return this->time_length; - } -} - -static uint32_t demux_ogg_get_capabilities(demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; - int cap_chapter = 0; - - if (this->chapter_info) - cap_chapter = DEMUX_CAP_CHAPTERS; - - return DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG | cap_chapter; -} - -static int format_lang_string (demux_ogg_t * this, uint32_t buf_mask, uint32_t buf_type, int channel, char *str) { - int stream_num; - - for (stream_num=0; stream_num<this->num_streams; stream_num++) { - if ((this->si[stream_num]->buf_types & buf_mask) == buf_type) { - if (this->si[stream_num]->language) { - if (snprintf (str, XINE_LANG_MAX, "%s", this->si[stream_num]->language) >= XINE_LANG_MAX) - /* the string got truncated */ - str[XINE_LANG_MAX - 2] = str[XINE_LANG_MAX - 3] = str[XINE_LANG_MAX - 4] = '.'; - /* TODO: provide long version in XINE_META_INFO_FULL_LANG */ - } else { - snprintf(str, XINE_LANG_MAX, "channel %d",channel); - } - return DEMUX_OPTIONAL_SUCCESS; - } - } - return DEMUX_OPTIONAL_UNSUPPORTED; -} - -static int demux_ogg_get_optional_data(demux_plugin_t *this_gen, - void *data, int data_type) { - - demux_ogg_t *this = (demux_ogg_t *) this_gen; - - char *str=(char *) data; - int channel = *((int *)data); - - switch (data_type) { - case DEMUX_OPTIONAL_DATA_SPULANG: - lprintf ("DEMUX_OPTIONAL_DATA_SPULANG channel = %d\n",channel); - if (channel==-1) { - strcpy( str, "none"); - return DEMUX_OPTIONAL_SUCCESS; - } else if ((channel>=0) && (channel<this->num_streams)) { - return format_lang_string (this, 0xFFFFFFFF, BUF_SPU_OGM+channel, channel, str); - } - return DEMUX_OPTIONAL_UNSUPPORTED; - case DEMUX_OPTIONAL_DATA_AUDIOLANG: - lprintf ("DEMUX_OPTIONAL_DATA_AUDIOLANG channel = %d\n",channel); - if (channel==-1) { - return format_lang_string (this, 0xFF00001F, BUF_AUDIO_BASE, channel, str); - } else if ((channel>=0) && (channel<this->num_streams)) { - return format_lang_string (this, 0xFF00001F, BUF_AUDIO_BASE+channel, channel, str); - } - return DEMUX_OPTIONAL_UNSUPPORTED; - default: - return DEMUX_OPTIONAL_UNSUPPORTED; - } -} - -static int detect_ogg_content (int detection_method, demux_class_t *class_gen, - input_plugin_t *input) { - - switch (detection_method) { - - case METHOD_BY_CONTENT: { - uint8_t buf[4]; - - if (_x_demux_read_header(input, buf, 4) != 4) - return 0; - - if ((buf[0] == 'O') && (buf[1] == 'g') && (buf[2] == 'g') && - (buf[3] == 'S')) - return 1; - else - return 0; - } - - case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); - - if (_x_demux_check_extension (mrl, extensions)) - return 1; - else - return 0; - } - - case METHOD_EXPLICIT: - return 1; - - default: - return 0; - } -} - -static int detect_anx_content (int detection_method, demux_class_t *class_gen, - input_plugin_t *input) { - - if (detect_ogg_content(detection_method, class_gen, input) == 0) - return 0; - - switch (detection_method) { - -#define ANNODEX_SIGNATURE_SEARCH 128 - - case METHOD_BY_CONTENT: { - uint8_t buf[ANNODEX_SIGNATURE_SEARCH]; - int found_annodex_signature = 0; - const char *annodex_signature = "Annodex"; - int annodex_signature_length = 7; /* = strlen(annodex_signature) */ - int i, j; - - if (_x_demux_read_header(input, buf, ANNODEX_SIGNATURE_SEARCH) != - ANNODEX_SIGNATURE_SEARCH) - return 0; - - /* scan for 'Annodex' signature in the first 64 bytes */ - for (i = 0, j = 0; i < ANNODEX_SIGNATURE_SEARCH; i++) { - if (buf[i] == annodex_signature[j]) { - if (j >= annodex_signature_length) { - /* found signature */ - found_annodex_signature = 1; - break; - } else { - j++; - } - } - } - - if (found_annodex_signature) - return 1; - else - return 0; - } - -#undef ANNODEX_SIGNATURE_SEARCH - - case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); - - if (_x_demux_check_extension (mrl, extensions)) - return 1; - else - return 0; - } - - case METHOD_EXPLICIT: - return 1; - - default: - return 0; - } -} - -static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, - input_plugin_t *input) { - - demux_ogg_t *this; - - if (detect_anx_content(stream->content_detection_method, class_gen, input) == 0) - return NULL; - - /* - * if we reach this point, the input has been accepted. - */ - - this = xine_xmalloc (sizeof (demux_ogg_t)); - memset (this, 0, sizeof(demux_ogg_t)); - this->stream = stream; - this->input = input; - - /* the Annodex demuxer currently calls into exactly the same functions as - * the Ogg demuxer, which seems to make this function a bit redundant, but - * this design leaves us a bit more room to change an Annodex demuxer's - * behaviour in the future if necessary */ - this->demux_plugin.send_headers = demux_ogg_send_headers; - this->demux_plugin.send_chunk = demux_ogg_send_chunk; - this->demux_plugin.seek = demux_ogg_seek; - 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.get_capabilities = demux_ogg_get_capabilities; - this->demux_plugin.get_optional_data = demux_ogg_get_optional_data; - this->demux_plugin.demux_class = class_gen; - - this->status = DEMUX_FINISHED; - -#ifdef HAVE_THEORA - theora_info_init (&this->t_info); - theora_comment_init (&this->t_comment); -#endif - - this->chapter_info = 0; - this->title = 0; - this->event_queue = xine_event_new_queue (this->stream); - - return &this->demux_plugin; -} - -static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, - input_plugin_t *input) { - - demux_ogg_t *this; - - if (detect_ogg_content(stream->content_detection_method, class_gen, input) == 0) - return NULL; - - /* - * if we reach this point, the input has been accepted. - */ - - this = xine_xmalloc (sizeof (demux_ogg_t)); - memset (this, 0, sizeof(demux_ogg_t)); - this->stream = stream; - this->input = input; - - this->demux_plugin.send_headers = demux_ogg_send_headers; - this->demux_plugin.send_chunk = demux_ogg_send_chunk; - this->demux_plugin.seek = demux_ogg_seek; - 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.get_capabilities = demux_ogg_get_capabilities; - this->demux_plugin.get_optional_data = demux_ogg_get_optional_data; - this->demux_plugin.demux_class = class_gen; - - this->status = DEMUX_FINISHED; - -#ifdef HAVE_THEORA - theora_info_init (&this->t_info); - theora_comment_init (&this->t_comment); -#endif - - this->chapter_info = 0; - this->title = 0; - this->event_queue = xine_event_new_queue (this->stream); - - return &this->demux_plugin; -} - -/* - * Annodex demuxer class - */ - -static const char *anx_get_description (demux_class_t *this_gen) { - return "Annodex demux plugin"; -} - -static const char *anx_get_identifier (demux_class_t *this_gen) { - return "Annodex"; -} - -static const char *anx_get_extensions (demux_class_t *this_gen) { - return "anx axa axv"; -} - -static const char *anx_get_mimetypes (demux_class_t *this_gen) { - return "application/x-annodex: ogg: Annodex media;"; -} - -static void anx_class_dispose (demux_class_t *this_gen) { - demux_anx_class_t *this = (demux_anx_class_t *) this_gen; - - free (this); -} - -static void *anx_init_class (xine_t *xine, void *data) { - demux_anx_class_t *this; - - this = xine_xmalloc (sizeof (demux_anx_class_t)); - - this->demux_class.open_plugin = anx_open_plugin; - this->demux_class.get_description = anx_get_description; - this->demux_class.get_identifier = anx_get_identifier; - this->demux_class.get_mimetypes = anx_get_mimetypes; - this->demux_class.get_extensions = anx_get_extensions; - this->demux_class.dispose = anx_class_dispose; - - return this; -} - -/* - * ogg demuxer class - */ - -static const char *ogg_get_description (demux_class_t *this_gen) { - return "OGG demux plugin"; -} - -static const char *ogg_get_identifier (demux_class_t *this_gen) { - return "OGG"; -} - -static const char *ogg_get_extensions (demux_class_t *this_gen) { - return "ogg ogm spx"; -} - -static const char *ogg_get_mimetypes (demux_class_t *this_gen) { - return "audio/x-ogg: ogg: OggVorbis Audio;" - "audio/x-speex: ogg: Speex Audio;" - "application/x-ogg: ogg: Ogg Stream;" - "application/ogg: ogg: Ogg Stream;"; -} - -static void ogg_class_dispose (demux_class_t *this_gen) { - demux_ogg_class_t *this = (demux_ogg_class_t *) this_gen; - - free (this); -} - -static void *ogg_init_class (xine_t *xine, void *data) { - demux_ogg_class_t *this; - - this = xine_xmalloc (sizeof (demux_ogg_class_t)); - - this->demux_class.open_plugin = ogg_open_plugin; - this->demux_class.get_description = ogg_get_description; - this->demux_class.get_identifier = ogg_get_identifier; - this->demux_class.get_mimetypes = ogg_get_mimetypes; - this->demux_class.get_extensions = ogg_get_extensions; - this->demux_class.dispose = ogg_class_dispose; - - return this; -} - -/* - * exported plugin catalog entry - */ -static const demuxer_info_t demux_info_anx = { - 20 /* priority */ -}; - -static const demuxer_info_t demux_info_ogg = { - 10 /* priority */ -}; - -const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 26, "ogg", XINE_VERSION_CODE, &demux_info_ogg, ogg_init_class }, - { PLUGIN_DEMUX, 26, "anx", XINE_VERSION_CODE, &demux_info_anx, anx_init_class }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; |