X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fkate.c;h=3c648566530b6047ffb5f848f697ad2b868ff5be;hb=17e07afce4d26cfecf6ab5252c738cd8a0e9756a;hp=0e8a899834f5afb58e0435979ea9793d37cdce22;hpb=c93c7588a67eafdb20b5771a6c2055b8308f2560;p=vlc diff --git a/modules/codec/kate.c b/modules/codec/kate.c index 0e8a899834..3c64856653 100644 --- a/modules/codec/kate.c +++ b/modules/codec/kate.c @@ -1,24 +1,24 @@ /***************************************************************************** * kate.c : a decoder for the kate bitstream format ***************************************************************************** - * Copyright (C) 2000-2008 the VideoLAN team + * Copyright (C) 2000-2008 VLC authors and VideoLAN * $Id$ * * Authors: Vincent Penquerc'h * - * This program 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 + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -32,7 +32,7 @@ #include #include #include -#include +#include "../demux/xiph.h" #include #ifdef HAVE_TIGER @@ -73,8 +73,7 @@ struct decoder_sys_t /* * Input properties */ - int i_num_headers; - int i_headers; + bool b_has_headers; /* * Kate properties @@ -88,6 +87,7 @@ struct decoder_sys_t * Common properties */ mtime_t i_pts; + mtime_t i_max_stop; /* decoder_sys_t is shared between decoder and spu units */ vlc_mutex_t lock; @@ -98,8 +98,6 @@ struct decoder_sys_t * Tiger properties */ tiger_renderer *p_tr; - subpicture_t *p_spu_final; - mtime_t last_render_ts; bool b_dirty; uint32_t i_tiger_default_font_color; @@ -117,7 +115,7 @@ struct decoder_sys_t bool b_use_tiger; }; -struct subpicture_sys_t +struct subpicture_updater_sys_t { decoder_sys_t *p_dec_sys; mtime_t i_start; @@ -279,47 +277,46 @@ vlc_module_begin () set_subcategory( SUBCAT_INPUT_SCODEC ) add_shortcut( "kate" ) - add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT, - true ); + add_bool( "kate-formatted", true, FORMAT_TEXT, FORMAT_LONGTEXT, + true ) #ifdef HAVE_TIGER - add_bool( "kate-use-tiger", true, NULL, TIGER_TEXT, TIGER_LONGTEXT, - true ); + add_bool( "kate-use-tiger", true, TIGER_TEXT, TIGER_LONGTEXT, + true ) add_float_with_range( "kate-tiger-quality", - TIGER_QUALITY_DEFAULT, 0.0f, 1.0f, TigerConfigurationCallback, + TIGER_QUALITY_DEFAULT, 0.0f, 1.0f, TIGER_QUALITY_TEXT, TIGER_QUALITY_LONGTEXT, - true ); + true ) set_section( N_("Tiger rendering defaults"), NULL ); - add_string( "kate-tiger-default-font-desc", - TIGER_DEFAULT_FONT_DESC_DEFAULT, TigerConfigurationCallback, + add_string( "kate-tiger-default-font-desc", TIGER_DEFAULT_FONT_DESC_DEFAULT, TIGER_DEFAULT_FONT_DESC_TEXT, TIGER_DEFAULT_FONT_DESC_LONGTEXT, true); add_integer_with_range( "kate-tiger-default-font-effect", TIGER_DEFAULT_FONT_EFFECT_DEFAULT, - 0, sizeof(pi_font_effects)/sizeof(pi_font_effects[0])-1, TigerConfigurationCallback, + 0, sizeof(pi_font_effects)/sizeof(pi_font_effects[0])-1, TIGER_DEFAULT_FONT_EFFECT_TEXT, TIGER_DEFAULT_FONT_EFFECT_LONGTEXT, - true ); - change_integer_list( pi_font_effects, ppsz_font_effect_names, NULL ); + true ) + change_integer_list( pi_font_effects, ppsz_font_effect_names ); add_float_with_range( "kate-tiger-default-font-effect-strength", - TIGER_DEFAULT_FONT_EFFECT_STRENGTH_DEFAULT, 0.0f, 1.0f, TigerConfigurationCallback, + TIGER_DEFAULT_FONT_EFFECT_STRENGTH_DEFAULT, 0.0f, 1.0f, TIGER_DEFAULT_FONT_EFFECT_STRENGTH_TEXT, TIGER_DEFAULT_FONT_EFFECT_STRENGTH_LONGTEXT, - true ); + true ) add_integer_with_range( "kate-tiger-default-font-color", - TIGER_DEFAULT_FONT_COLOR_DEFAULT, 0, 0x00ffffff, TigerConfigurationCallback, + TIGER_DEFAULT_FONT_COLOR_DEFAULT, 0, 0x00ffffff, TIGER_DEFAULT_FONT_COLOR_TEXT, TIGER_DEFAULT_FONT_COLOR_LONGTEXT, true); - change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ); + change_integer_list( pi_color_values, ppsz_color_descriptions ); add_integer_with_range( "kate-tiger-default-font-alpha", - TIGER_DEFAULT_FONT_ALPHA_DEFAULT, 0, 255, TigerConfigurationCallback, + TIGER_DEFAULT_FONT_ALPHA_DEFAULT, 0, 255, TIGER_DEFAULT_FONT_ALPHA_TEXT, TIGER_DEFAULT_FONT_ALPHA_LONGTEXT, true); add_integer_with_range( "kate-tiger-default-background-color", - TIGER_DEFAULT_BACKGROUND_COLOR_DEFAULT, 0, 0x00ffffff, TigerConfigurationCallback, + TIGER_DEFAULT_BACKGROUND_COLOR_DEFAULT, 0, 0x00ffffff, TIGER_DEFAULT_BACKGROUND_COLOR_TEXT, TIGER_DEFAULT_BACKGROUND_COLOR_LONGTEXT, true); - change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ); + change_integer_list( pi_color_values, ppsz_color_descriptions ); add_integer_with_range( "kate-tiger-default-background-alpha", - TIGER_DEFAULT_BACKGROUND_ALPHA_DEFAULT, 0, 255, TigerConfigurationCallback, + TIGER_DEFAULT_BACKGROUND_ALPHA_DEFAULT, 0, 255, TIGER_DEFAULT_BACKGROUND_ALPHA_TEXT, TIGER_DEFAULT_BACKGROUND_ALPHA_LONGTEXT, true); #endif @@ -344,15 +341,14 @@ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; - int i_ret; - msg_Dbg( p_dec, "kate: OpenDecoder"); - - if( p_dec->fmt_in.i_codec != VLC_FOURCC('k','a','t','e') ) + if( p_dec->fmt_in.i_codec != VLC_CODEC_KATE ) { return VLC_EGENERIC; } + msg_Dbg( p_dec, "kate: OpenDecoder"); + /* Set callbacks */ p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **)) DecodeBlock; @@ -360,8 +356,7 @@ static int OpenDecoder( vlc_object_t *p_this ) DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = p_sys = - (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) + if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL ) return VLC_ENOMEM; vlc_mutex_init( &p_sys->lock ); @@ -373,13 +368,13 @@ static int OpenDecoder( vlc_object_t *p_this ) p_sys->b_packetizer = false; #endif p_sys->b_ready = false; - p_sys->i_pts = 0; + p_sys->i_pts = + p_sys->i_max_stop = VLC_TS_INVALID; kate_comment_init( &p_sys->kc ); kate_info_init( &p_sys->ki ); - p_sys->i_num_headers = 0; - p_sys->i_headers = 0; + p_sys->b_has_headers = false; /* retrieve options */ p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" ); @@ -391,7 +386,6 @@ static int OpenDecoder( vlc_object_t *p_this ) p_sys->b_use_tiger = var_CreateGetBool( p_dec, "kate-use-tiger" ); p_sys->p_tr = NULL; - p_sys->last_render_ts = 0; /* get initial value of configuration */ p_sys->i_tiger_default_font_color = GetTigerColor( p_dec, "kate-tiger-default-font" ); @@ -403,21 +397,22 @@ static int OpenDecoder( vlc_object_t *p_this ) if( p_sys->b_use_tiger ) { - i_ret = tiger_renderer_create( &p_sys->p_tr ); + int i_ret = tiger_renderer_create( &p_sys->p_tr ); if( i_ret < 0 ) { msg_Warn ( p_dec, "Failed to create Tiger renderer, falling back to basic rendering" ); p_sys->p_tr = NULL; p_sys->b_use_tiger = false; } - - CHECK_TIGER_RET( tiger_renderer_set_surface_clear_color( p_sys->p_tr, 1, 0, 0, 0, 0 ) ); - - UpdateTigerFontEffect( p_dec ); - UpdateTigerFontColor( p_dec ); - UpdateTigerBackgroundColor( p_dec ); - UpdateTigerQuality( p_dec ); - UpdateTigerFontDesc( p_dec ); + else { + CHECK_TIGER_RET( tiger_renderer_set_surface_clear_color( p_sys->p_tr, 1, 0, 0, 0, 0 ) ); + + UpdateTigerFontEffect( p_dec ); + UpdateTigerFontColor( p_dec ); + UpdateTigerBackgroundColor( p_dec ); + UpdateTigerQuality( p_dec ); + UpdateTigerFontDesc( p_dec ); + } } #else @@ -426,8 +421,10 @@ static int OpenDecoder( vlc_object_t *p_this ) #endif + es_format_Init( &p_dec->fmt_out, SPU_ES, 0 ); + /* add the decoder to the global list */ - decoder_t **list = ( decoder_t** ) realloc( kate_decoder_list, (kate_decoder_list_size+1) * sizeof( decoder_t* )); + decoder_t **list = realloc( kate_decoder_list, (kate_decoder_list_size+1) * sizeof( *list )); if( list ) { list[ kate_decoder_list_size++ ] = p_dec; @@ -449,7 +446,7 @@ static int OpenPacketizer( vlc_object_t *p_this ) if( i_ret == VLC_SUCCESS ) { p_dec->p_sys->b_packetizer = true; - p_dec->fmt_out.i_codec = VLC_FOURCC( 'k', 'a', 't', 'e' ); + p_dec->fmt_out.i_codec = VLC_CODEC_KATE; } return i_ret; @@ -472,20 +469,18 @@ static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) p_block = *pp_block; - if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) ) - { - block_Release( p_block ); - return NULL; - } - - if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY) ) + if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) { #ifdef HAVE_TIGER - /* Hmm, should we wait before flushing the renderer ? I think not, but not certain... */ - vlc_mutex_lock( &p_sys->lock ); - tiger_renderer_seek( p_sys->p_tr, 0 ); - vlc_mutex_unlock( &p_sys->lock ); + if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY) + { + /* Hmm, should we wait before flushing the renderer ? I think not, but not certain... */ + vlc_mutex_lock( &p_sys->lock ); + tiger_renderer_seek( p_sys->p_tr, 0 ); + vlc_mutex_unlock( &p_sys->lock ); + } #endif + p_sys->i_max_stop = VLC_TS_INVALID; block_Release( p_block ); return NULL; } @@ -493,42 +488,14 @@ static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) /* Block to Kate packet */ kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer); - if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra ) + if( !p_sys->b_has_headers ) { - /* Headers already available as extra data */ - p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0]; - p_sys->i_headers = p_sys->i_num_headers; - } - else if( kp.nbytes && (p_sys->i_headers==0 || p_sys->i_headers < p_sys->ki.num_headers )) - { - /* Backup headers as extra data */ - uint8_t *p_extra; - - p_dec->fmt_in.p_extra = - realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra + kp.nbytes + 2 ); - p_extra = (void*)(((unsigned char*)p_dec->fmt_in.p_extra) + p_dec->fmt_in.i_extra); - *(p_extra++) = kp.nbytes >> 8; - *(p_extra++) = kp.nbytes & 0xFF; - - memcpy( p_extra, kp.data, kp.nbytes ); - p_dec->fmt_in.i_extra += kp.nbytes + 2; - - block_Release( *pp_block ); - p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0]; - p_sys->i_headers++; - return NULL; - } - - if( p_sys->i_headers == p_sys->i_num_headers && p_sys->i_num_headers>0 ) - { - if( ProcessHeaders( p_dec ) != VLC_SUCCESS ) + if( ProcessHeaders( p_dec ) ) { - p_sys->i_headers = 0; - p_dec->fmt_in.i_extra = 0; block_Release( *pp_block ); return NULL; } - else p_sys->i_headers++; + p_sys->b_has_headers = true; } return ProcessPacket( p_dec, &kp, pp_block ); @@ -541,33 +508,21 @@ static int ProcessHeaders( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; kate_packet kp; - uint8_t *p_extra; - int i_extra; - int i_headeridx; - int i_ret; - - if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC; - - p_extra = p_dec->fmt_in.p_extra; - i_extra = p_dec->fmt_in.i_extra; - /* skip number of headers */ - ++p_extra; - --i_extra; + unsigned pi_size[XIPH_MAX_HEADER_COUNT]; + void *pp_data[XIPH_MAX_HEADER_COUNT]; + unsigned i_count; + if( xiph_SplitHeaders( pi_size, pp_data, &i_count, + p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) ) + return VLC_EGENERIC; - /* Take care of the initial Kate header */ - kp.nbytes = *(p_extra++) << 8; - kp.nbytes |= (*(p_extra++) & 0xFF); - kp.data = p_extra; - p_extra += kp.nbytes; - i_extra -= (kp.nbytes + 2); - if( i_extra < 0 ) - { - msg_Err( p_dec, "header data corrupted"); + if( i_count < 1 ) return VLC_EGENERIC; - } - i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); + /* Take care of the initial Kate header */ + kp.nbytes = pi_size[0]; + kp.data = pp_data[0]; + int i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( i_ret < 0 ) { msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", i_ret ); @@ -580,19 +535,10 @@ static int ProcessHeaders( decoder_t *p_dec ) p_sys->ki.granule_shift); /* parse all remaining header packets */ - for( i_headeridx = 1; i_headeridx < p_sys->ki.num_headers; ++i_headeridx ) + for( unsigned i_headeridx = 1; i_headeridx < i_count; i_headeridx++ ) { - kp.nbytes = *(p_extra++) << 8; - kp.nbytes |= (*(p_extra++) & 0xFF); - kp.data = p_extra; - p_extra += kp.nbytes; - i_extra -= (kp.nbytes + 2); - if( i_extra < 0 ) - { - msg_Err( p_dec, "header %d data corrupted", i_headeridx ); - return VLC_EGENERIC; - } - + kp.nbytes = pi_size[i_headeridx]; + kp.data = pp_data[i_headeridx]; i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( i_ret < 0 ) { @@ -625,8 +571,8 @@ static int ProcessHeaders( decoder_t *p_dec ) else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; - p_dec->fmt_out.p_extra = - realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); + p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, + p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); } @@ -646,7 +592,7 @@ static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp, subpicture_t *p_buf = NULL; /* Date management */ - if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts ) + if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != p_sys->i_pts ) { p_sys->i_pts = p_block->i_pts; } @@ -669,12 +615,10 @@ static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp, else #endif { - if( p_sys->i_headers >= p_sys->i_num_headers && p_sys->i_num_headers > 0) - p_buf = DecodePacket( p_dec, p_kp, p_block ); - else - p_buf = NULL; + p_buf = DecodePacket( p_dec, p_kp, p_block ); - if( p_block ) block_Release( p_block ); + if( p_block ) + block_Release( p_block ); } return p_buf; @@ -703,44 +647,19 @@ static void GetVideoSize( decoder_t *p_dec, int *w, int *h ) { /* searching for vout to get its size is frowned upon, so we don't and use a default size if the original canvas size is not specified. */ -#if 1 decoder_sys_t *p_sys = p_dec->p_sys; if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 ) { *w = p_sys->ki.original_canvas_width; *h = p_sys->ki.original_canvas_height; - msg_Dbg( p_dec, "original canvas %zu %zu\n", + msg_Dbg( p_dec, "original canvas %zu %zu", p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height ); } else { /* nothing, leave defaults */ - msg_Dbg( p_dec, "original canvas size unknown\n"); - } -#else - /* keep this just in case it might be allowed one day ;) */ - vout_thread_t *p_vout; - p_vout = vlc_object_find( (vlc_object_t*)p_dec, VLC_OBJECT_VOUT, FIND_CHILD ); - if( p_vout ) - { - decoder_sys_t *p_sys = p_dec->p_sys; - if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 ) - { - *w = p_sys->ki.original_canvas_width; - *h = p_sys->ki.original_canvas_height; - } - else - { - *w = p_vout->fmt_in.i_width; - *h = p_vout->fmt_in.i_height; - } - msg_Dbg( p_dec, "video: in %d %d, out %d %d, original canvas %zu %zu\n", - p_vout->fmt_in.i_width, p_vout->fmt_in.i_height, - p_vout->fmt_out.i_width, p_vout->fmt_out.i_height, - p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height ); - vlc_object_release( p_vout ); + msg_Dbg( p_dec, "original canvas size unknown"); } -#endif } static void CreateKateBitmap( picture_t *pic, const kate_bitmap *bitmap ) @@ -813,28 +732,9 @@ static void SetupText( decoder_t *p_dec, subpicture_t *p_spu, const kate_event * static void TigerDestroySubpicture( subpicture_t *p_subpic ) { - DecSysRelease( p_subpic->p_sys->p_dec_sys ); + DecSysRelease( p_subpic->updater.p_sys->p_dec_sys ); + free( p_subpic->updater.p_sys ); } - -static void SubpictureReleaseRegions( subpicture_t *p_subpic ) -{ - if( p_subpic->p_region) - { - subpicture_region_ChainDelete( p_subpic->p_region ); - p_subpic->p_region = NULL; - } -} - -static void TigerPreRender( spu_t *p_spu, subpicture_t *p_subpic, const video_format_t *p_fmt ) -{ - decoder_sys_t *p_sys = p_subpic->p_sys->p_dec_sys; - - VLC_UNUSED( p_spu ); - VLC_UNUSED( p_fmt ); - - p_sys->p_spu_final = p_subpic; -} - /* * We get premultiplied alpha, but VLC doesn't expect this, so we demultiply * alpha to avoid double multiply (and thus thinner text than we should)). @@ -863,15 +763,15 @@ static void PostprocessTigerImage( plane_t *p_plane, unsigned int i_width ) if( a ) { #ifdef WORDS_BIGENDIAN - uint8_t tmp = pixel[2]; - p_pixel[0] = p_pixel[3] * 255 / a; + uint8_t tmp = p_pixel[2]; + p_pixel[0] = clip_uint8_vlc((p_pixel[3] * 255 + a / 2) / a); p_pixel[3] = a; - p_pixel[2] = p_pixel[1] * 255 / a; - p_pixel[1] = tmp * 255 / a; + p_pixel[2] = clip_uint8_vlc((p_pixel[1] * 255 + a / 2) / a); + p_pixel[1] = clip_uint8_vlc((tmp * 255 + a / 2) / a); #else - p_pixel[0] = p_pixel[0] * 255 / a; - p_pixel[1] = p_pixel[1] * 255 / a; - p_pixel[2] = p_pixel[2] * 255 / a; + p_pixel[0] = clip_uint8_vlc((p_pixel[0] * 255 + a / 2) / a); + p_pixel[1] = clip_uint8_vlc((p_pixel[1] * 255 + a / 2) / a); + p_pixel[2] = clip_uint8_vlc((p_pixel[2] * 255 + a / 2) / a); #endif } else @@ -886,82 +786,78 @@ static void PostprocessTigerImage( plane_t *p_plane, unsigned int i_width ) PROFILE_STOP( tiger_renderer_postprocess ); } -/* Tiger renders can end up looking a bit crap since they get overlaid on top of - a subsampled YUV image, so there can be a fair amount of chroma bleeding. - Looks good with white though since it's all luma. Hopefully that will be the - common case. */ -static void TigerUpdateRegions( spu_t *p_spu, subpicture_t *p_subpic, const video_format_t *p_fmt, mtime_t ts ) +static int TigerValidateSubpicture( subpicture_t *p_subpic, + bool b_fmt_src, const video_format_t *p_fmt_src, + bool b_fmt_dst, const video_format_t *p_fmt_dst, + mtime_t ts ) { - decoder_sys_t *p_sys = p_subpic->p_sys->p_dec_sys; - subpicture_region_t *p_r; - video_format_t fmt; - plane_t *p_plane; - kate_float t; - int i_ret; + VLC_UNUSED(p_fmt_src); VLC_UNUSED(p_fmt_dst); - VLC_UNUSED( p_spu ); - - PROFILE_START( TigerUpdateRegions ); - - /* do not render more than once per frame, libtiger renders all events at once */ - if (ts <= p_sys->last_render_ts) - { - SubpictureReleaseRegions( p_subpic ); - return; - } + decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys; - /* remember what frame we've rendered already */ - p_sys->last_render_ts = ts; + if( b_fmt_src || b_fmt_dst ) + return VLC_EGENERIC; - if( p_subpic != p_sys->p_spu_final ) - { - SubpictureReleaseRegions( p_subpic ); - return; - } + PROFILE_START( TigerValidateSubpicture ); /* time in seconds from the start of the stream */ - t = (p_subpic->p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f; + kate_float t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f; /* it is likely that the current region (if any) can be kept as is; test for this */ vlc_mutex_lock( &p_sys->lock ); - if( p_subpic->p_region && !p_sys->b_dirty && !tiger_renderer_is_dirty( p_sys->p_tr )) + int i_ret; + if( p_sys->b_dirty || tiger_renderer_is_dirty( p_sys->p_tr ) ) { - PROFILE_START( tiger_renderer_update1 ); - i_ret = tiger_renderer_update( p_sys->p_tr, t, 1 ); - PROFILE_STOP( tiger_renderer_update1 ); - if( i_ret < 0 ) - { - SubpictureReleaseRegions( p_subpic ); - vlc_mutex_unlock( &p_sys->lock ); - return; - } - - if( !tiger_renderer_is_dirty( p_sys->p_tr ) ) - { - /* we can keep the current region list */ - PROFILE_STOP( TigerUpdateRegions ); - vlc_mutex_unlock( &p_sys->lock ); - return; - } + i_ret = VLC_EGENERIC; + goto exit; } + if( tiger_renderer_update( p_sys->p_tr, t, 1 ) >= 0 && + tiger_renderer_is_dirty( p_sys->p_tr ) ) + { + i_ret = VLC_EGENERIC; + goto exit; + } + + i_ret = VLC_SUCCESS; +exit: vlc_mutex_unlock( &p_sys->lock ); + PROFILE_STOP( TigerValidateSubpicture ); + return i_ret; +} + +/* Tiger renders can end up looking a bit crap since they get overlaid on top of + a subsampled YUV image, so there can be a fair amount of chroma bleeding. + Looks good with white though since it's all luma. Hopefully that will be the + common case. */ +static void TigerUpdateSubpicture( subpicture_t *p_subpic, + const video_format_t *p_fmt_src, + const video_format_t *p_fmt_dst, + mtime_t ts ) +{ + decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys; + plane_t *p_plane; + kate_float t; + int i_ret; + - /* we have to render again, reset current region list */ - SubpictureReleaseRegions( p_subpic ); + /* time in seconds from the start of the stream */ + t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f; + + PROFILE_START( TigerUpdateSubpicture ); /* create a full frame region - this will also tell Tiger the size of the frame */ - fmt = *p_fmt; - fmt.i_chroma = VLC_FOURCC('R','G','B','A'); - fmt.i_width = fmt.i_visible_width; - fmt.i_height = fmt.i_visible_height; + video_format_t fmt = *p_fmt_dst; + fmt.i_chroma = VLC_CODEC_RGBA; fmt.i_bits_per_pixel = 0; - fmt.i_x_offset = fmt.i_y_offset = 0; + fmt.i_width = + fmt.i_visible_width = p_fmt_src->i_width; + fmt.i_height = + fmt.i_visible_height = p_fmt_src->i_height; + fmt.i_x_offset = fmt.i_y_offset = 0; - p_r = subpicture_region_New( &fmt ); + subpicture_region_t *p_r = subpicture_region_New( &fmt ); if( !p_r ) - { return; - } p_r->i_x = 0; p_r->i_y = 0; @@ -996,7 +892,7 @@ static void TigerUpdateRegions( spu_t *p_spu, subpicture_t *p_subpic, const vide p_subpic->p_region = p_r; p_sys->b_dirty = false; - PROFILE_STOP( TigerUpdateRegions ); + PROFILE_STOP( TigerUpdateSubpicture ); vlc_mutex_unlock( &p_sys->lock ); @@ -1110,7 +1006,7 @@ static int OnConfigurationChanged( decoder_t *p_dec, const char *psz_var, vlc_mutex_lock( &p_sys->lock ); - msg_Dbg( p_dec, "OnConfigurationChanged: %s\n", psz_var ); + msg_Dbg( p_dec, "OnConfigurationChanged: %s", psz_var ); if( !p_sys->b_use_tiger || !p_sys->p_tr ) { @@ -1249,44 +1145,51 @@ static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t /* we have an event */ /* Get a new spu */ - p_spu = decoder_NewSubpicture( p_dec ); + subpicture_updater_sys_t *p_spu_sys = NULL; + if( p_sys->b_use_tiger) + { + p_spu_sys = malloc( sizeof(*p_spu_sys) ); + if( !p_spu_sys ) + return NULL; + } + subpicture_updater_t updater = { +#ifdef HAVE_TIGER + .pf_validate = TigerValidateSubpicture, + .pf_update = TigerUpdateSubpicture, + .pf_destroy = TigerDestroySubpicture, +#endif + .p_sys = p_spu_sys, + }; + p_spu = decoder_NewSubpicture( p_dec, p_sys->b_use_tiger ? &updater : NULL ); if( !p_spu ) { + free( p_spu_sys ); /* this will happen for lyrics as there is no vout - so no error */ /* msg_Err( p_dec, "Failed to allocate spu buffer" ); */ return NULL; } p_spu->i_start = p_block->i_pts; - p_spu->i_stop = p_block->i_pts + INT64_C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator; + p_spu->i_stop = p_block->i_pts + CLOCK_FREQ * + ev->duration * p_sys->ki.gps_denominator / p_sys->ki.gps_numerator; p_spu->b_ephemer = false; p_spu->b_absolute = false; #ifdef HAVE_TIGER if( p_sys->b_use_tiger) { - /* setup the structure to get our decoder struct back */ - p_spu->p_sys = malloc( sizeof( subpicture_sys_t )); - if( !p_spu->p_sys ) - { - decoder_DeleteSubpicture( p_dec, p_spu ); - return NULL; - } - p_spu->p_sys->p_dec_sys = p_sys; - p_spu->p_sys->i_start = p_block->i_pts; + p_spu_sys->p_dec_sys = p_sys; + p_spu_sys->i_start = p_block->i_pts; DecSysHold( p_sys ); + p_spu->i_stop = __MAX( p_sys->i_max_stop, p_spu->i_stop ); + p_spu->b_ephemer = true; p_spu->b_absolute = true; /* add the event to tiger */ vlc_mutex_lock( &p_sys->lock ); CHECK_TIGER_RET( tiger_renderer_add_event( p_sys->p_tr, ev->ki, ev ) ); vlc_mutex_unlock( &p_sys->lock ); - - /* hookup render/update routines */ - p_spu->pf_pre_render = TigerPreRender; - p_spu->pf_update_regions = TigerUpdateRegions; - p_spu->pf_destroy = TigerDestroySubpicture; } else #endif @@ -1347,8 +1250,7 @@ static subpicture_t *SetupSimpleKateSPU( decoder_t *p_dec, subpicture_t *p_spu, /* create a separate region for the bitmap */ memset( &fmt, 0, sizeof(video_format_t) ); - fmt.i_chroma = VLC_FOURCC('Y','U','V','P'); - fmt.i_aspect = 0; + fmt.i_chroma = VLC_CODEC_YUVP; fmt.i_width = fmt.i_visible_width = ev->bitmap->width; fmt.i_height = fmt.i_visible_height = ev->bitmap->height; fmt.i_x_offset = fmt.i_y_offset = 0; @@ -1359,26 +1261,29 @@ static subpicture_t *SetupSimpleKateSPU( decoder_t *p_dec, subpicture_t *p_spu, if( !p_bitmap_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); - decoder_DeleteSubpicture( p_dec, p_spu ); + subpicture_Delete( p_spu ); return NULL; } /* create the bitmap */ CreateKateBitmap( p_bitmap_region->p_picture, ev->bitmap ); - msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors\n", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors); + msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors); } /* text region */ - fmt.i_chroma = VLC_FOURCC('T','E','X','T'); - fmt.i_aspect = 0; + fmt.i_chroma = VLC_CODEC_TEXT; + fmt.i_sar_num = 0; + fmt.i_sar_den = 1; fmt.i_width = fmt.i_height = 0; fmt.i_x_offset = fmt.i_y_offset = 0; p_spu->p_region = subpicture_region_New( &fmt ); if( !p_spu->p_region ) { msg_Err( p_dec, "cannot allocate SPU region" ); - decoder_DeleteSubpicture( p_dec, p_spu ); + if( p_bitmap_region ) + subpicture_region_Delete( p_bitmap_region ); + subpicture_Delete( p_spu ); return NULL; } @@ -1498,8 +1403,7 @@ static void DecSysRelease( decoder_sys_t *p_sys ) #ifdef HAVE_TIGER if( p_sys->p_tr ) tiger_renderer_destroy( p_sys->p_tr ); - if( p_sys->psz_tiger_default_font_desc ) - free( p_sys->psz_tiger_default_font_desc ); + free( p_sys->psz_tiger_default_font_desc ); #endif if (p_sys->b_ready)