X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fspudec%2Fspudec.c;h=f527a9c2b379c0ed5fc6cc6ff48cc353859719ef;hb=7a4f28303162b32b456d4f09f75a6f15a1de805b;hp=599606e46806f56564c40fa0354ea8b4150eba8f;hpb=2ea3cbd32148ee3b0737cf1a439a122849efde58;p=vlc diff --git a/modules/codec/spudec/spudec.c b/modules/codec/spudec/spudec.c index 599606e468..f527a9c2b3 100644 --- a/modules/codec/spudec/spudec.c +++ b/modules/codec/spudec/spudec.c @@ -1,16 +1,17 @@ /***************************************************************************** * spudec.c : SPU decoder thread ***************************************************************************** - * Copyright (C) 2000-2001 VideoLAN - * $Id: spudec.c,v 1.12 2003/01/20 02:45:25 titer Exp $ + * Copyright (C) 2000-2001, 2006 the VideoLAN team + * $Id$ * - * Authors: Samuel Hocevar + * Authors: Sam Hocevar + * Laurent Aimar * * 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 * (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 @@ -18,248 +19,232 @@ * * 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, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include /* memcpy(), memset() */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include -#include -#include +#include +#include +#include #include "spudec.h" /***************************************************************************** - * Local prototypes + * Module descriptor. *****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int RunDecoder ( decoder_fifo_t * ); -static int InitThread ( spudec_thread_t * ); -static void EndThread ( spudec_thread_t * ); +static int DecoderOpen ( vlc_object_t * ); +static int PacketizerOpen( vlc_object_t * ); +static void Close ( vlc_object_t * ); + +vlc_module_begin () + set_description( N_("DVD subtitles decoder") ) + set_capability( "decoder", 50 ) + set_category( CAT_INPUT ) + set_subcategory( SUBCAT_INPUT_SCODEC ) + set_callbacks( DecoderOpen, Close ) + + add_submodule () + set_description( N_("DVD subtitles packetizer") ) + set_capability( "packetizer", 50 ) + set_callbacks( PacketizerOpen, Close ) +vlc_module_end () /***************************************************************************** - * Module descriptor. + * Local prototypes *****************************************************************************/ -#define FONT_TEXT N_("Font used by the text subtitler") -#define FONT_LONGTEXT N_(\ - "When the subtitles are coded in text form then, you can choose " \ - "which font will be used to display them.") - -#define DEFAULT_FONT "font-eutopiabold36.rle" - -vlc_module_begin(); - add_category_hint( N_("subtitles"), NULL ); -#if defined(SYS_DARWIN) || defined(SYS_BEOS) - add_file( "spudec-font", NULL, NULL, - FONT_TEXT, FONT_LONGTEXT ); -#else - add_file( "spudec-font", "./share/" DEFAULT_FONT, NULL, - FONT_TEXT, FONT_LONGTEXT ); -#endif - set_description( _("subtitles decoder module") ); - set_capability( "decoder", 50 ); - set_callbacks( OpenDecoder, NULL ); -vlc_module_end(); +static block_t * Reassemble( decoder_t *, block_t ** ); +static subpicture_t * Decode ( decoder_t *, block_t ** ); +static block_t * Packetize ( decoder_t *, block_t ** ); /***************************************************************************** - * OpenDecoder: probe the decoder and return score + * DecoderOpen ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able + * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/ -static int OpenDecoder( vlc_object_t *p_this ) +static int DecoderOpen( vlc_object_t *p_this ) { - decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this; + decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - if( p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ') - && p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') - && p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') ) + if( p_dec->fmt_in.i_codec != VLC_FOURCC( 's','p','u',' ' ) && + p_dec->fmt_in.i_codec != VLC_FOURCC( 's','p','u','b' ) ) { return VLC_EGENERIC; } - p_fifo->pf_run = RunDecoder; + p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); + + p_sys->b_packetizer = false; + p_sys->i_spu_size = 0; + p_sys->i_spu = 0; + p_sys->p_block = NULL; + + es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) ); + + p_dec->pf_decode_sub = Decode; + p_dec->pf_packetize = NULL; return VLC_SUCCESS; } /***************************************************************************** - * RunDecoder: this function is called just after the thread is created + * PacketizerOpen + ***************************************************************************** + * Tries to launch a decoder and return score so that the interface is able + * to chose. *****************************************************************************/ -static int RunDecoder( decoder_fifo_t * p_fifo ) +static int PacketizerOpen( vlc_object_t *p_this ) { - spudec_thread_t * p_spudec; - subtitler_font_t * p_font; - char * psz_font; - - /* Allocate the memory needed to store the thread's structure */ - p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) ); + decoder_t *p_dec = (decoder_t*)p_this; - if ( p_spudec == NULL ) + if( DecoderOpen( p_this ) ) { - msg_Err( p_fifo, "out of memory" ); - DecoderError( p_fifo ); - return( -1 ); + return VLC_EGENERIC; } - - /* - * Initialize the thread properties - */ - p_spudec->p_vout = NULL; - p_spudec->p_fifo = p_fifo; - - /* - * Initialize thread and free configuration - */ - p_spudec->p_fifo->b_error = InitThread( p_spudec ); - - /* - * Main loop - it is not executed if an error occured during - * initialization - */ - if( p_fifo->i_fourcc == VLC_FOURCC('s','u','b','t') ) - { - /* Here we are dealing with text subtitles */ - -#if defined(SYS_DARWIN) || defined(SYS_BEOS) - if ( (psz_font = config_GetPsz( p_fifo, "spudec-font" )) == NULL ) - { - char * psz_vlcpath = p_fifo->p_libvlc->psz_vlcpath; - psz_font = malloc( strlen(psz_vlcpath) + strlen("/share/") - + strlen(DEFAULT_FONT) + 1 ); - sprintf(psz_font, "%s/share/" DEFAULT_FONT, psz_vlcpath); - } -#else - if( (psz_font = config_GetPsz( p_fifo, "spudec-font" )) == NULL ) - { - msg_Err( p_fifo, "no default font selected" ); - p_font = NULL; - p_spudec->p_fifo->b_error; - } - else -#endif - { - p_font = E_(subtitler_LoadFont)( p_spudec->p_vout, psz_font ); - if ( p_font == NULL ) - { - msg_Err( p_fifo, "unable to load font: %s", psz_font ); - p_spudec->p_fifo->b_error; - } - } - if( psz_font ) free( psz_font ); + p_dec->pf_packetize = Packetize; + p_dec->p_sys->b_packetizer = true; + es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); + p_dec->fmt_out.i_codec = VLC_FOURCC( 's','p','u',' ' ); - while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) ) - { - E_(ParseText)( p_spudec, p_font ); - } + return VLC_SUCCESS; +} - if( p_font ) E_(subtitler_UnloadFont)( p_spudec->p_vout, p_font ); +/***************************************************************************** + * Close: + *****************************************************************************/ +static void Close( vlc_object_t *p_this ) +{ + decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys = p_dec->p_sys; - } - else + if( p_sys->p_block ) { - /* Here we are dealing with sub-pictures subtitles*/ + block_ChainRelease( p_sys->p_block ); + } - while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) ) - { - if( E_(SyncPacket)( p_spudec ) ) - { - continue; - } + free( p_sys ); +} - E_(ParsePacket)( p_spudec ); - } - } +/***************************************************************************** + * Decode: + *****************************************************************************/ +static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_spu_block; + subpicture_t *p_spu; - /* - * Error loop - */ - if( p_spudec->p_fifo->b_error ) - { - DecoderError( p_spudec->p_fifo ); + p_spu_block = Reassemble( p_dec, pp_block ); - /* End of thread */ - EndThread( p_spudec ); - return -1; + if( ! p_spu_block ) + { + return NULL; } - /* End of thread */ - EndThread( p_spudec ); - return 0; -} + /* FIXME: what the, we shouldn’t need to allocate 64k of buffer --sam. */ + p_sys->i_spu = block_ChainExtract( p_spu_block, p_sys->buffer, 65536 ); + p_sys->i_pts = p_spu_block->i_pts; + block_ChainRelease( p_spu_block ); + + /* Parse and decode */ + p_spu = ParsePacket( p_dec ); -/* following functions are local */ + /* reinit context */ + p_sys->i_spu_size = 0; + p_sys->i_rle_size = 0; + p_sys->i_spu = 0; + p_sys->p_block = NULL; + + return p_spu; +} /***************************************************************************** - * InitThread: initialize spu decoder thread - ***************************************************************************** - * This function is called from RunThread and performs the second step of the - * initialization. It returns 0 on success. Note that the thread's flag are not - * modified inside this function. + * Packetize: *****************************************************************************/ -static int InitThread( spudec_thread_t *p_spudec ) +static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) { - /* Find an available video output */ - do + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_spu = Reassemble( p_dec, pp_block ); + + if( ! p_spu ) { - if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error ) - { - /* Call InitBitstream anyway so p_spudec->bit_stream is in a known - * state before calling CloseBitstream */ - InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo, - NULL, NULL ); - return -1; - } + return NULL; + } - p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT, - FIND_ANYWHERE ); + p_spu->i_dts = p_spu->i_pts; + p_spu->i_length = 0; - if( p_spudec->p_vout ) - { - break; - } - - msleep( VOUT_OUTMEM_SLEEP ); - } - while( 1 ); + /* reinit context */ + p_sys->i_spu_size = 0; + p_sys->i_rle_size = 0; + p_sys->i_spu = 0; + p_sys->p_block = NULL; - return InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo, - NULL, NULL ); + return block_ChainGather( p_spu ); } /***************************************************************************** - * EndThread: thread destruction - ***************************************************************************** - * This function is called when the thread ends after a sucessful - * initialization. + * Reassemble: *****************************************************************************/ -static void EndThread( spudec_thread_t *p_spudec ) +static block_t *Reassemble( decoder_t *p_dec, block_t **pp_block ) { - if( p_spudec->p_vout != NULL - && p_spudec->p_vout->p_subpicture != NULL ) + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; + + if( pp_block == NULL || *pp_block == NULL ) return NULL; + p_block = *pp_block; + *pp_block = NULL; + + if( p_sys->i_spu_size <= 0 && + ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) ) + { + msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" ); + msg_Dbg( p_dec, "spu size: %d, i_pts: %"PRId64" i_buffer: %zu", + p_sys->i_spu_size, p_block->i_pts, p_block->i_buffer ); + block_Release( p_block ); + return NULL; + } + + block_ChainAppend( &p_sys->p_block, p_block ); + p_sys->i_spu += p_block->i_buffer; + + if( p_sys->i_spu_size <= 0 ) { - subpicture_t * p_subpic; - int i_subpic; - - for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ ) + p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )| + p_block->p_buffer[1]; + p_sys->i_rle_size = ( ( p_block->p_buffer[2] << 8 )| + p_block->p_buffer[3] ) - 4; + + /* msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d", + p_sys->i_spu_size, p_sys->i_rle_size ); */ + + if( p_sys->i_spu_size <= 0 || p_sys->i_rle_size >= p_sys->i_spu_size ) { - p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic]; - - if( p_subpic != NULL && - ( ( p_subpic->i_status == RESERVED_SUBPICTURE ) - || ( p_subpic->i_status == READY_SUBPICTURE ) ) ) - { - vout_DestroySubPicture( p_spudec->p_vout, p_subpic ); - } + p_sys->i_spu_size = 0; + p_sys->i_rle_size = 0; + p_sys->i_spu = 0; + p_sys->p_block = NULL; + + block_Release( p_block ); + return NULL; } + } + + if( p_sys->i_spu >= p_sys->i_spu_size ) + { + /* We have a complete sub */ + if( p_sys->i_spu > p_sys->i_spu_size ) + msg_Dbg( p_dec, "SPU packets size=%d should be %d", + p_sys->i_spu, p_sys->i_spu_size ); - vlc_object_release( p_spudec->p_vout ); + return p_sys->p_block; } - - CloseBitstream( &p_spudec->bit_stream ); - free( p_spudec ); + return NULL; }