spudec.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:8k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * spudec.c : SPU decoder thread
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2001, 2006 the VideoLAN team
  5.  * $Id: f527a9c2b379c0ed5fc6cc6ff48cc353859719ef $
  6.  *
  7.  * Authors: Sam Hocevar <sam@zoy.org>
  8.  *          Laurent Aimar <fenrir@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_codec.h>
  33. #include "spudec.h"
  34. /*****************************************************************************
  35.  * Module descriptor.
  36.  *****************************************************************************/
  37. static int  DecoderOpen   ( vlc_object_t * );
  38. static int  PacketizerOpen( vlc_object_t * );
  39. static void Close         ( vlc_object_t * );
  40. vlc_module_begin ()
  41.     set_description( N_("DVD subtitles decoder") )
  42.     set_capability( "decoder", 50 )
  43.     set_category( CAT_INPUT )
  44.     set_subcategory( SUBCAT_INPUT_SCODEC )
  45.     set_callbacks( DecoderOpen, Close )
  46.     add_submodule ()
  47.     set_description( N_("DVD subtitles packetizer") )
  48.     set_capability( "packetizer", 50 )
  49.     set_callbacks( PacketizerOpen, Close )
  50. vlc_module_end ()
  51. /*****************************************************************************
  52.  * Local prototypes
  53.  *****************************************************************************/
  54. static block_t *      Reassemble( decoder_t *, block_t ** );
  55. static subpicture_t * Decode    ( decoder_t *, block_t ** );
  56. static block_t *      Packetize ( decoder_t *, block_t ** );
  57. /*****************************************************************************
  58.  * DecoderOpen
  59.  *****************************************************************************
  60.  * Tries to launch a decoder and return score so that the interface is able
  61.  * to chose.
  62.  *****************************************************************************/
  63. static int DecoderOpen( vlc_object_t *p_this )
  64. {
  65.     decoder_t     *p_dec = (decoder_t*)p_this;
  66.     decoder_sys_t *p_sys;
  67.     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 's','p','u',' ' ) &&
  68.         p_dec->fmt_in.i_codec != VLC_FOURCC( 's','p','u','b' ) )
  69.     {
  70.         return VLC_EGENERIC;
  71.     }
  72.     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
  73.     p_sys->b_packetizer = false;
  74.     p_sys->i_spu_size = 0;
  75.     p_sys->i_spu      = 0;
  76.     p_sys->p_block    = NULL;
  77.     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 's','p','u',' ' ) );
  78.     p_dec->pf_decode_sub = Decode;
  79.     p_dec->pf_packetize  = NULL;
  80.     return VLC_SUCCESS;
  81. }
  82. /*****************************************************************************
  83.  * PacketizerOpen
  84.  *****************************************************************************
  85.  * Tries to launch a decoder and return score so that the interface is able
  86.  * to chose.
  87.  *****************************************************************************/
  88. static int PacketizerOpen( vlc_object_t *p_this )
  89. {
  90.     decoder_t *p_dec = (decoder_t*)p_this;
  91.     if( DecoderOpen( p_this ) )
  92.     {
  93.         return VLC_EGENERIC;
  94.     }
  95.     p_dec->pf_packetize  = Packetize;
  96.     p_dec->p_sys->b_packetizer = true;
  97.     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
  98.     p_dec->fmt_out.i_codec = VLC_FOURCC( 's','p','u',' ' );
  99.     return VLC_SUCCESS;
  100. }
  101. /*****************************************************************************
  102.  * Close:
  103.  *****************************************************************************/
  104. static void Close( vlc_object_t *p_this )
  105. {
  106.     decoder_t     *p_dec = (decoder_t*)p_this;
  107.     decoder_sys_t *p_sys = p_dec->p_sys;
  108.     if( p_sys->p_block )
  109.     {
  110.         block_ChainRelease( p_sys->p_block );
  111.     }
  112.     free( p_sys );
  113. }
  114. /*****************************************************************************
  115.  * Decode:
  116.  *****************************************************************************/
  117. static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
  118. {
  119.     decoder_sys_t *p_sys = p_dec->p_sys;
  120.     block_t       *p_spu_block;
  121.     subpicture_t  *p_spu;
  122.     p_spu_block = Reassemble( p_dec, pp_block );
  123.     if( ! p_spu_block )
  124.     {
  125.         return NULL;
  126.     }
  127.     /* FIXME: what the, we shouldn’t need to allocate 64k of buffer --sam. */
  128.     p_sys->i_spu = block_ChainExtract( p_spu_block, p_sys->buffer, 65536 );
  129.     p_sys->i_pts = p_spu_block->i_pts;
  130.     block_ChainRelease( p_spu_block );
  131.     /* Parse and decode */
  132.     p_spu = ParsePacket( p_dec );
  133.     /* reinit context */
  134.     p_sys->i_spu_size = 0;
  135.     p_sys->i_rle_size = 0;
  136.     p_sys->i_spu      = 0;
  137.     p_sys->p_block    = NULL;
  138.     return p_spu;
  139. }
  140. /*****************************************************************************
  141.  * Packetize:
  142.  *****************************************************************************/
  143. static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
  144. {
  145.     decoder_sys_t *p_sys = p_dec->p_sys;
  146.     block_t       *p_spu = Reassemble( p_dec, pp_block );
  147.     if( ! p_spu )
  148.     {
  149.         return NULL;
  150.     }
  151.     p_spu->i_dts = p_spu->i_pts;
  152.     p_spu->i_length = 0;
  153.     /* reinit context */
  154.     p_sys->i_spu_size = 0;
  155.     p_sys->i_rle_size = 0;
  156.     p_sys->i_spu      = 0;
  157.     p_sys->p_block    = NULL;
  158.     return block_ChainGather( p_spu );
  159. }
  160. /*****************************************************************************
  161.  * Reassemble:
  162.  *****************************************************************************/
  163. static block_t *Reassemble( decoder_t *p_dec, block_t **pp_block )
  164. {
  165.     decoder_sys_t *p_sys = p_dec->p_sys;
  166.     block_t *p_block;
  167.     if( pp_block == NULL || *pp_block == NULL ) return NULL;
  168.     p_block = *pp_block;
  169.     *pp_block = NULL;
  170.     if( p_sys->i_spu_size <= 0 &&
  171.         ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) )
  172.     {
  173.         msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" );
  174.         msg_Dbg( p_dec, "spu size: %d, i_pts: %"PRId64" i_buffer: %zu",
  175.                  p_sys->i_spu_size, p_block->i_pts, p_block->i_buffer );
  176.         block_Release( p_block );
  177.         return NULL;
  178.     }
  179.     block_ChainAppend( &p_sys->p_block, p_block );
  180.     p_sys->i_spu += p_block->i_buffer;
  181.     if( p_sys->i_spu_size <= 0 )
  182.     {
  183.         p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )|
  184.             p_block->p_buffer[1];
  185.         p_sys->i_rle_size = ( ( p_block->p_buffer[2] << 8 )|
  186.             p_block->p_buffer[3] ) - 4;
  187.         /* msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d",
  188.                     p_sys->i_spu_size, p_sys->i_rle_size ); */
  189.         if( p_sys->i_spu_size <= 0 || p_sys->i_rle_size >= p_sys->i_spu_size )
  190.         {
  191.             p_sys->i_spu_size = 0;
  192.             p_sys->i_rle_size = 0;
  193.             p_sys->i_spu      = 0;
  194.             p_sys->p_block    = NULL;
  195.             block_Release( p_block );
  196.             return NULL;
  197.         }
  198.     }
  199.     if( p_sys->i_spu >= p_sys->i_spu_size )
  200.     {
  201.         /* We have a complete sub */
  202.         if( p_sys->i_spu > p_sys->i_spu_size )
  203.             msg_Dbg( p_dec, "SPU packets size=%d should be %d",
  204.                      p_sys->i_spu, p_sys->i_spu_size );
  205.         return p_sys->p_block;
  206.     }
  207.     return NULL;
  208. }