diff options
Diffstat (limited to 'src/libsputext/xine_decoder.c')
-rw-r--r-- | src/libsputext/xine_decoder.c | 305 |
1 files changed, 164 insertions, 141 deletions
diff --git a/src/libsputext/xine_decoder.c b/src/libsputext/xine_decoder.c index e4db27b16..d6b3d3666 100644 --- a/src/libsputext/xine_decoder.c +++ b/src/libsputext/xine_decoder.c @@ -17,15 +17,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_decoder.c,v 1.42 2003/01/10 22:23:54 miguelfreitas Exp $ + * $Id: xine_decoder.c,v 1.43 2003/01/11 03:47:01 miguelfreitas Exp $ * - * code based on mplayer module: - * - * Subtitle reader with format autodetection - * - * Written by laaz - * Some code cleanup & realloc() by A'rpi/ESP-team - * dunnowhat sub format by szabi */ #include <stdlib.h> @@ -77,6 +70,7 @@ typedef struct sputext_decoder_s { int output_open; + int lines; char text[SUB_MAX_TEXT][SUB_BUFSIZE]; float mpsub_position; @@ -85,7 +79,6 @@ typedef struct sputext_decoder_s { int height; /* frame height */ int font_size; int line_height; - int uses_time; char *font; @@ -95,6 +88,7 @@ typedef struct sputext_decoder_s { osd_renderer_t *renderer; osd_object_t *osd; + int64_t img_duration; int64_t last_subtitle_end; /* no new subtitle before this vpts */ } sputext_decoder_t; @@ -135,154 +129,181 @@ static void update_font_size (sputext_decoder_t *this) { } } -static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { - sputext_decoder_t *this = (sputext_decoder_t *) this_gen; - int64_t current_time; - uint32_t start, end; +static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t sub_end ) { - if( !this->width || !this->height || !this->renderer ) { - + int line, y; + int font_size; + + this->renderer->filled_rect (this->osd, 0, 0, this->width-1, this->line_height * SUB_MAX_TEXT - 1, 0); + + y = (SUB_MAX_TEXT - this->lines) * this->line_height; + font_size = this->font_size; + + for (line=0; line<this->lines; line++) { + int w,h,x; + + while(1) { + this->renderer->get_text_size( this->osd, this->text[line], + &w, &h); + x = (this->width - w) / 2; + + if( w > this->width && font_size > 16 ) { + font_size -= 4; + this->renderer->set_font (this->osd, this->font, font_size); + } else { + break; + } + } + + this->renderer->render_text (this->osd, x, y + line*this->line_height, + this->text[line], OSD_TEXT1); } + + if( font_size != this->font_size ) + this->renderer->set_font (this->osd, this->font, this->font_size); + + if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) { + sub_start = this->last_subtitle_end; + } + this->last_subtitle_end = sub_end; + + this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1); + this->renderer->show (this->osd, sub_start); + this->renderer->hide (this->osd, sub_end); + +//#ifdef LOG + printf ("sputext: scheduling subtitle >%s< at %lld until %lld, current time is %lld\n", + this->text[0], sub_start, sub_end, + this->stream->xine->clock->get_current_time (this->stream->xine->clock)); +//#endif +} -#if 0 - if (buf->decoder_flags & BUF_FLAG_HEADER) { - this->width = buf->decoder_info[1]; - this->height = buf->decoder_info[2]; - - this->renderer = this->stream->osd_renderer; - this->osd = NULL; - - update_font_size (this); - - current_time = this->stream->xine->clock->get_current_time (this->stream->xine->clock); - this->renderer->show (this->osd, current_time); - this->renderer->hide (this->osd, current_time+300000); - - } else { - int64_t sub_start, sub_end; +static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { - /* don't want to see subtitle */ - if(this->stream->spu_channel_user == -2) - return; + sputext_decoder_t *this = (sputext_decoder_t *) this_gen; + int uses_time; + int32_t start, end, diff; + int64_t start_vpts, end_vpts; + int i; + uint32_t *val; + char *str; + extra_info_t extra_info; + int seek_count; + int status; + + val = (uint32_t * )buf->content; + this->lines = *val++; + uses_time = *val++; + start = *val++; + end = *val++; + str = (char *)val; + for (i = 0; i < this->lines; i++, str+=strlen(str)+1) { + strcpy( this->text[i], str ); + } + + printf("libsputext: decoder data [%s]\n", this->text[0]); + printf("libsputext: mode %d timming %d->%d\n", uses_time, start, end); + if( end <= start ) { + printf("libsputext: discarding subtitle with invalid timming\n"); + } + + if( this->stream->master_stream ) + xine_get_current_info (this->stream->master_stream, &extra_info, sizeof(extra_info) ); + else + xine_get_current_info (this->stream, &extra_info, sizeof(extra_info) ); + seek_count = extra_info.seek_count; - /* - * find out which subtitle to display - */ - if (!this->uses_time) { - int frame_num; - int64_t pts_factor; - long frame_offset; - - frame_num = buf->decoder_info[1]; - - /* FIXME FIXME FIXME - pts_factor = this->stream->metronom->get_video_rate (this->stream->metronom); - */ - pts_factor = 3000; - - frame_offset = this->time_offset * 900 / pts_factor; - - while ( (this->cur < this->num) - && (this->text[this->cur].start + frame_offset < frame_num) ) - this->cur++; - - if (this->cur >= this->num) - return; - - subtitle = &this->subtitles[this->cur]; - - if (subtitle->start + frame_offset > frame_num) - return; - - sub_start = this->stream->metronom->got_spu_packet(this->stream->metronom, buf->pts); - sub_end = sub_start + (subtitle->end - subtitle->start) * pts_factor; - - } else { - uint32_t start_tenth; - - start_tenth = buf->pts/900; - -#ifdef LOG - printf ("sputext: searching for spu for %d\n", start_tenth); -#endif - - while ( (this->cur < this->num) - && (this->subtitles[this->cur].start + this->time_offset < start_tenth) ) - this->cur++; - - if (this->cur >= this->num) - return; - -#ifdef LOG - printf ("sputext: found >%s<, start %ld, end %ld\n", this->subtitles[this->cur].text[0], - this->subtitles[this->cur].start + this->time_offset, this->subtitles[this->cur].end); -#endif - - subtitle = &this->subtitles[this->cur]; - - if (subtitle->start + this->time_offset > (start_tenth+20)) - return; - - sub_start = this->stream->metronom->got_spu_packet(this->stream->metronom, (subtitle->start+this->time_offset)*900); - sub_end = sub_start + (subtitle->end - subtitle->start)*900; + do { + + /* initialize decoder if needed */ + if( !this->width || !this->height ) { + + if( this->stream->video_out->status(this->stream->video_out, NULL, + &this->width, &this->height )) { + + if( this->width && this->height ) { + this->renderer = this->stream->osd_renderer; + + if( this->stream->master_stream ) + this->img_duration = this->stream->master_stream->metronom->get_option( + this->stream->master_stream->metronom, METRONOM_FRAME_DURATION); + else + this->img_duration = this->stream->metronom->get_option( + this->stream->metronom, METRONOM_FRAME_DURATION); + + this->osd = NULL; + + update_font_size (this); + } + } } - - if( !sub_start ) - return; - - if (subtitle) { - int line, y; - int font_size; - - this->renderer->filled_rect (this->osd, 0, 0, this->width-1, this->line_height * SUB_MAX_TEXT - 1, 0); - - y = (SUB_MAX_TEXT - subtitle->lines) * this->line_height; - font_size = this->font_size; + + if( this->osd && this->last_subtitle_end < extra_info.vpts ) { - for (line=0; line<subtitle->lines; line++) { - int w,h,x; + /* try to use frame number mode */ + if( !uses_time && extra_info.frame_number ) { + + diff = end - extra_info.frame_number; - while(1) { - this->renderer->get_text_size( this->osd, subtitle->text[line], - &w, &h); - x = (this->width - w) / 2; + /* discard old subtitles */ + if( diff < 0 ) + return; - if( w > this->width && font_size > 16 ) { - font_size -= 4; - this->renderer->set_font (this->osd, this->font, font_size); - } else { - break; - } + diff = start - extra_info.frame_number; + + /* draw it if less than 2 seconds left */ + if( diff < 2*90000 / this->img_duration ) { + start_vpts = extra_info.vpts + diff * this->img_duration; + end_vpts = start_vpts + (end-start) * this->img_duration; + + draw_subtitle(this, start_vpts, end_vpts); + return; } - this->renderer->render_text (this->osd, x, y + line*this->line_height, subtitle->text[line], OSD_TEXT1); - } - - if( font_size != this->font_size ) - this->renderer->set_font (this->osd, this->font, this->font_size); - - if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) { - sub_start = this->last_subtitle_end; - } - this->last_subtitle_end = sub_end; + } else { - this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1); - this->renderer->show (this->osd, sub_start); - this->renderer->hide (this->osd, sub_end); - -#ifdef LOG - printf ("sputext: scheduling subtitle >%s< at %lld until %lld, current time is %lld\n", - subtitle->text[0], sub_start, sub_end, - this->stream->metronom->get_current_time (this->stream->metronom)); -#endif - + if( !uses_time ) { + start = start * this->img_duration / 90; + end = end * this->img_duration / 90; + uses_time = 1; + } + + diff = end - extra_info.input_time; + + /* discard old subtitles */ + if( diff < 0 ) + return; + + diff = start - extra_info.input_time; + + /* draw it if less than 2 seconds left */ + if( diff < 2000 ) { + start_vpts = extra_info.vpts + diff * 90; + end_vpts = start_vpts + (end-start) * 90; + + draw_subtitle(this, start_vpts, end_vpts); + return; + } + } } - this->cur++; - } -#endif + + xine_usec_sleep (50000); + + if( this->stream->master_stream ) + xine_get_current_info (this->stream->master_stream, &extra_info, sizeof(extra_info) ); + else + xine_get_current_info (this->stream, &extra_info, sizeof(extra_info) ); + + if( this->stream->master_stream ) + status = xine_get_status (this->stream->master_stream); + else + status = xine_get_status (this->stream); + + } while(seek_count == extra_info.seek_count && status != XINE_STATUS_QUIT && + status != XINE_STATUS_STOP); } @@ -395,6 +416,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { sputext_class_t *this ; + printf("libsputext: init class\n"); + this = (sputext_class_t *) xine_xmalloc (sizeof (sputext_class_t)); this->class.open_plugin = sputext_class_open_plugin; |