From: Bastien N. <ha...@ha...> - 2003-04-30 09:04:12
|
Hello Andreas, Good work on the demuxer and decoder, but as you can see from the diff below, you broke/reverted a bunch of fixes that were made recently. 1) We don't need the LOGs defined 2) You broke OGM subtitles it seems 3) You downgraded the plugin API version 4) You removed the work-around for streams without a syncpoint. I left the diff attached so that you could see. Good work on this plugin anyway :) On Wed, 2003-04-30 at 09:49, Andreas Heinchen wrote: > Update of /cvsroot/xine/xine-lib/src/demuxers > In directory sc8-pr-cvs1:/tmp/cvs-serv8817/xine-lib/src/demuxers > Index: demux_ogg.c > =================================================================== > RCS file: /cvsroot/xine/xine-lib/src/demuxers/demux_ogg.c,v > retrieving revision 1.85 > retrieving revision 1.86 > diff -u -r1.85 -r1.86 > --- demux_ogg.c 27 Apr 2003 17:40:59 -0000 1.85 > +++ demux_ogg.c 30 Apr 2003 08:49:39 -0000 1.86 > @@ -1,4 +1,3 @@ > - > /* > * Copyright (C) 2000-2003 the xine project > * > @@ -39,13 +38,17 @@ > #include <ogg/ogg.h> > #include <vorbis/codec.h> > > +#ifdef HAVE_THEORA > +#include <theora/theora.h> > +#endif > + > #include "xine_internal.h" > #include "xineutils.h" > #include "demux.h" > > -/* > + > #define LOG > - */ > + We don't need the LOGs > #define CHUNKSIZE 8500 > #define PACKET_TYPE_HEADER 0x01 > @@ -75,8 +78,12 @@ > > input_plugin_t *input; > > +#ifdef HAVE_THEORA > + theora_info t_info; > +#endif > + > int status; > - > + > int frame_duration; > > ogg_sync_state oy; > @@ -87,8 +94,8 @@ > uint32_t buf_types[MAX_STREAMS]; > int preview_buffers[MAX_STREAMS]; > int64_t header_granulepos[MAX_STREAMS]; > - int factor[MAX_STREAMS]; > - int quotient[MAX_STREAMS]; > + int64_t factor[MAX_STREAMS]; > + int64_t quotient[MAX_STREAMS]; > > int num_streams; > > @@ -104,6 +111,7 @@ > int keyframe_needed; > int ignore_keyframes; > int time_length; > + > } demux_ogg_t ; > > > @@ -117,6 +125,15 @@ > config_values_t *config; > } demux_ogg_class_t; > > +static int intlog(int num) { > + int ret=0; > + while(num>0){ > + num=num/2; > + ret=ret+1; > + } > + return(ret); > +} > + > static int get_stream (demux_ogg_t *this, int serno) > { > int i; > @@ -129,13 +146,30 @@ > } > > static int get_pts (demux_ogg_t *this, int stream_num , int64_t granulepos ) { > - if (this->quotient[stream_num]) > + /*calculates an pts from an granulepos*/ > + if (granulepos<0) { > + if ( this->header_granulepos[stream_num]>=0 ) > + return get_pts (this, stream_num, this->header_granulepos[stream_num]); > + else > + return 0; > + > +#ifdef HAVE_THEORA > + } else if (this->buf_types[stream_num]==BUF_VIDEO_THEORA) { > + int64_t iframe,pframe; > + int keyframe_granule_shift; > + keyframe_granule_shift=intlog(this->t_info.keyframe_frequency_force-1); > + iframe=granulepos>>keyframe_granule_shift; > + pframe=granulepos-(iframe<<keyframe_granule_shift); > + return ((iframe + pframe)*this->frame_duration); > +#endif > + > + } else if (this->quotient[stream_num]) > return (granulepos*this->factor[stream_num]/this->quotient[stream_num]); > else > return 0; > } > > -static int read_ogg_page (demux_ogg_t *this) { > +static int read_ogg_packet (demux_ogg_t *this) { > char *buffer; > long bytes; > while (ogg_sync_pageout(&this->oy,&this->og)!=1) { > @@ -162,6 +196,69 @@ > } > } > > +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) { > + /*this little function is used to send an entire ogg-packet through > + xine buffers to the appropiate decoder, where recieve_ogg_packet should be called to collect the > + buffers and reassemble them to an ogg packet*/ > + > + buf_element_t *buf; > + > + int done=0,todo=op->bytes; > + int op_size = sizeof(ogg_packet); > + > + /* nasty hack to pack op as well as (vorbis) content > + in one xine buffer */ > + > + buf = fifo->buffer_pool_alloc (fifo); > + memcpy (buf->content, op, op_size); > + > + if ( buf->max_size > op_size + todo ) { > + memcpy (buf->content + op_size , op->packet, todo); > + done=todo; > + buf->decoder_flags = BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END | decoder_flags; > + buf->size = op_size + done; > + } else { > + memcpy (buf->content + op_size , op->packet, buf->max_size - op_size ); > + done=done+ buf->max_size - op_size; > + buf->decoder_flags = BUF_FLAG_FRAME_START | decoder_flags; > + buf->size = buf->max_size; > + } > + > + buf->pts = pts; > + buf->extra_info->input_pos = this->input->get_current_pos (this->input); > + buf->extra_info->input_time = buf->pts / 90 ; > + buf->type = this->buf_types[stream_num] ; > + > + this->video_fifo->put (this->video_fifo, buf); > + > + while (done<todo) { > + buf = fifo->buffer_pool_alloc (fifo); > + if (done+buf->max_size < todo) { > + memcpy (buf->content, op->packet+done, buf->max_size); > + buf->size = buf->max_size; > + done=done+buf->max_size; > + buf->decoder_flags = decoder_flags; > + } else { > + memcpy (buf->content, op->packet+done, todo-done); > + buf->size = todo-done; > + done=todo; > + buf->decoder_flags = BUF_FLAG_FRAME_END | decoder_flags; > + } > + > + buf->pts = pts; > + buf->extra_info->input_pos = this->input->get_current_pos (this->input); > + buf->extra_info->input_time = buf->pts / 90 ; > + buf->type = this->buf_types[stream_num] ; > + > + fifo->put (fifo, buf); > + } > +} > + > /* redefine abs as macro to handle 64-bit diffs. > i guess llabs may not be available everywhere */ > #define abs(x) ( ((x)<0) ? -(x) : (x) ) > @@ -225,7 +322,7 @@ > 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) { > @@ -273,8 +370,34 @@ > > this->audio_fifo->put (this->audio_fifo, buf); > > +#ifdef HAVE_THEORA > + } else if ((this->buf_types[stream_num] & 0xFFFF0000) == BUF_VIDEO_THEORA) { > + > + int64_t pts; > + theora_info test; > + > + /*Lets see if this is an Header*/ > + if ((theora_decode_header(&test,op))>=0) { > + decoder_flags=decoder_flags|BUF_FLAG_HEADER; > +#ifdef LOG > + printf ("demux_ogg: found an header\n"); > +#endif > + } > + > + if (op->granulepos!=-1) { > + pts = get_pts (this, stream_num, op->granulepos); > + check_newpts( this, pts, PTS_VIDEO, decoder_flags ); > + } else if (this->header_granulepos[stream_num]!=-1) { > + pts = get_pts (this, stream_num, this->header_granulepos[stream_num]); > + this->header_granulepos[stream_num]=-1; > + check_newpts( this, pts, PTS_VIDEO, decoder_flags ); > + } else > + pts=0; > + send_ogg_packet (this, this->video_fifo, op, pts, decoder_flags, stream_num); > +#endif > + > } else if ((this->buf_types[stream_num] & 0xFF000000) == BUF_VIDEO_BASE) { > - > + > buf_element_t *buf; > int todo, done; > > @@ -314,7 +437,7 @@ > buf->pts = 0; > > #ifdef LOG > - printf ("demux_ogg: video granulepos %lld, pts %lld, time %d\n", op->granulepos, buf->pts, buf->pts / 90); > + printf ("demux_ogg: video granulepos %lld, pts %lld, time %lld\n", op->granulepos, buf->pts, buf->pts / 90); > #endif > > buf->extra_info->input_pos = this->input->get_current_pos (this->input); > @@ -350,6 +473,9 @@ > #endif > } else { > subtitle = (char *)&op->packet[hdrlen + 1]; > +#ifdef LOG > + printf ("demux_ogg: subtitle %d -> %d :%s\n",start,end,subtitle); > +#endif > if ((strlen(subtitle) > 1) || (*subtitle != ' ')) { > > start = op->granulepos; > @@ -387,7 +513,7 @@ > int filelength,position; > > ogg_packet op; > - > + > #ifdef LOG > printf ("demux_ogg: detecting stream types...\n"); > #endif > @@ -395,7 +521,7 @@ > this->ignore_keyframes = 0; > > while (!done) { > - if (!read_ogg_page(this)) { > + if (!read_ogg_packet(this)) { > this->status = DEMUX_FINISHED; > return; > } > @@ -497,7 +623,7 @@ > if( !this->buf_types[stream_num] ) > this->buf_types[stream_num] = BUF_VIDEO_UNKNOWN; > this->buf_types[stream_num] |= channel; > - this->preview_buffers[stream_num] = 1; /* FIXME: don't know */ > + this->preview_buffers[stream_num] = 5; /* FIXME: don't know */ > > #ifdef LOG > printf ("demux_ogg: subtype %.4s\n", &locsubtype); > @@ -623,7 +749,7 @@ > buf->decoder_info[3] = locchannels; > this->audio_fifo->put (this->audio_fifo, buf); > > - this->preview_buffers[stream_num] = 1; /* FIXME: don't know */ > + this->preview_buffers[stream_num] = 5; /* FIXME: don't know */ > this->factor[stream_num] = 90000; > this->quotient[stream_num] = locsamples_per_unit; > > @@ -654,7 +780,7 @@ > printf ("demux_ogg: older direct show filter-generated stream header detected.\n"); > hex_dump (op.packet, op.bytes); > #endif > - this->preview_buffers[stream_num] = 1; /* FIXME: don't know */ > + this->preview_buffers[stream_num] = 5; /* FIXME: don't know */ > > if ( (*(int32_t*)(op.packet+96)==0x05589f80) && (op.bytes>=184)) { > > @@ -763,9 +889,6 @@ > } > } else if (!strncmp (&op.packet[1], "text", 4)) { > int channel=0; > - uint32_t *val; > - buf_element_t *buf; > - > #ifdef LOG > printf ("demux_ogg: textstream detected.\n"); > #endif > @@ -773,15 +896,38 @@ > channel= this->num_spu_streams++; > this->buf_types[stream_num] = 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->buf_types[stream_num]; > - buf->pts = 0; > - val = (uint32_t * )buf->content; > - *val++=0; > - *val++=0; > - *val++=0; > - this->video_fifo->put (this->video_fifo, buf); > +#ifdef HAVE_THEORA > + } else if (!strncmp (&op.packet[1], "theora", 4)) { > + int channel; > + printf ("demux_ogg: Theorastreamsupport is highly alpha at the moment\n"); > + > + if (theora_decode_header(&this->t_info, &op)>=0) { > + > + this->num_video_streams++; > + > + this->factor[stream_num] = (int64_t) 90000 * (int64_t) this->t_info.fps_denominator; > + this->quotient[stream_num] = this->t_info.fps_numerator; > + > + this->frame_duration = ((int64_t) 90000*this->t_info.fps_denominator)/this->t_info.fps_numerator; > + > + this->preview_buffers[stream_num]=1; > + this->buf_types[stream_num] = BUF_VIDEO_THEORA; > + > + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] > + = this->t_info.width; > + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] > + = this->t_info.height; > + this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] > + = ((int64_t) 90000*this->t_info.fps_denominator)/this->t_info.fps_numerator; > + > + > + } else { > + /*Rejected stream*/ > + printf ("demux_ogg: A theora header was rejected by libtheora\n"); > + this->buf_types[stream_num] = BUF_CONTROL_NOP; > + this->preview_buffers[stream_num] = 5; /* FIXME: don't know */ > + } > +#endif > > } else { > printf ("demux_ogg: unknown stream type (signature >%.8s<). hex dump of bos packet follows:\n", > @@ -838,16 +984,15 @@ > this->demux_plugin.seek((demux_plugin_t *)this, (off_t) filelength-65536 ,0); > done=0; > while (!done) { > - if (!read_ogg_page (this)) > + if (!read_ogg_packet (this)) > 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))) > + 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; > } > } > - this->demux_plugin.seek((demux_plugin_t *)this, position,0); > } > } > } > @@ -863,13 +1008,14 @@ > printf ("demux_ogg: send package...\n"); > #endif > > - if (!read_ogg_page(this)) { > + if (!read_ogg_packet(this)) { > this->status = DEMUX_FINISHED; > #ifdef LOG > - printf ("demux_ogg: EOF\n"); > + printf ("demux_ogg: EOF\n"); > #endif > return; > } > + > /* now we've got one new page */ > > cur_serno = ogg_page_serialno (&this->og); > @@ -894,10 +1040,10 @@ > ogg_stream_pagein(&this->oss[stream_num], &this->og); > > if (ogg_page_bos(&this->og)) { > -#ifdef LOG > + > printf ("demux_ogg: beginning of stream\ndemux_ogg: serial number %d - discard\n", > ogg_page_serialno (&this->og)); > -#endif > + > while (ogg_stream_packetout(&this->oss[stream_num], &op) == 1) ; > return; > } > @@ -906,7 +1052,7 @@ > /* printf("demux_ogg: packet: %.8s\n", op.packet); */ > /* printf("demux_ogg: got a packet\n"); */ > > - if (*op.packet & PACKET_TYPE_HEADER) { > + if ((*op.packet & PACKET_TYPE_HEADER) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA)) { > if (op.granulepos!=-1) { > this->header_granulepos[stream_num]=op.granulepos; > #ifdef LOG > @@ -920,7 +1066,7 @@ > continue; > } > > - if (this->buf_flag_seek) > + if ((this->buf_flag_seek) && (this->buf_types[stream_num]!=BUF_VIDEO_THEORA)) > if ((op.granulepos==-1) && (this->header_granulepos[stream_num]==-1)) continue; > > > @@ -928,7 +1074,30 @@ > #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) && > + if (this->buf_types[stream_num] == BUF_VIDEO_THEORA) { > +#ifdef HAVE_THEORA > + > + int keyframe_granule_shift; > + int64_t pframe=-1,iframe=-1; > + > + keyframe_granule_shift=intlog(this->t_info.keyframe_frequency_force-1); > + > + /*replace the 1 with 0 and you will deactivate keyframeseeking*/ > + if (1) { > + if(op.granulepos>=0){ > + iframe=op.granulepos>>keyframe_granule_shift; > + pframe=op.granulepos-(iframe<<keyframe_granule_shift); > + printf ("seeking keyframe i %lld p %lld\n",iframe,pframe); > + if (pframe!=0) > + continue; > + } else > + continue; > + this->keyframe_needed = 0; > + } else > + this->keyframe_needed = 0; > + > +#endif > + } else 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", > @@ -1018,12 +1187,19 @@ > /* > * seek to start position > */ > +#ifdef LOG > + printf ("demux_ogg: seek called\n"); > +#endif > if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { > > this->keyframe_needed = (this->num_video_streams>0); > > if ( (!start_pos) && (start_time)) { > - start_pos = start_time * this->avg_bitrate/8; > + if (this->time_length!=-1) > + start_pos = start_time * 1000 * this->input->get_length(this->input) / this->time_length ; > + else > + start_pos = start_time * this->avg_bitrate/8; > + > #ifdef LOG > printf ("demux_ogg: seeking to %d seconds => %lld bytes\n", > start_time, start_pos); > @@ -1031,11 +1207,6 @@ > } > > ogg_sync_reset(&this->oy); > - > - /*some strange streams have no syncpoint flag set at the beginning*/ > - if (start_pos == 0) > - this->keyframe_needed = 0; > - > this->input->seek (this->input, start_pos, SEEK_SET); > } > > @@ -1224,7 +1395,7 @@ > > plugin_info_t xine_plugin_info[] = { > /* type, API, "name", version, special_info, init_function */ > - { PLUGIN_DEMUX, 21, "ogg", XINE_VERSION_CODE, NULL, init_class }, > + { PLUGIN_DEMUX, 20, "ogg", XINE_VERSION_CODE, NULL, init_class }, > { PLUGIN_NONE, 0, "", 0, NULL, NULL } > }; -- /Bastien Nocera http://hadess.net #2 0x4205a2cc in printf ("Oh my %s\n", preferred_deity) from /lib/i686/libc.so.6 printf ("Oh my %s\n", preferred_deity); Segmentation fault |