ogt_parse.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:13k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * Philips OGT (SVCD subtitle) packet parser
  3.  *****************************************************************************
  4.  * Copyright (C) 2003, 2004 VideoLAN
  5.  * $Id: ogt_parse.c 8709 2004-09-15 15:50:54Z gbazin $
  6.  *
  7.  * Author: Rocky Bernstein 
  8.  *   based on code from: 
  9.  *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
  10.  *       Sam Hocevar <sam@zoy.org>
  11.  *       Laurent Aimar <fenrir@via.ecp.fr>
  12.  *
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2 of the License, or
  16.  * (at your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; if not, write to the Free Software
  25.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  26.  *****************************************************************************/
  27. /*****************************************************************************
  28.  * Preamble
  29.  *****************************************************************************/
  30. #include <vlc/vlc.h>
  31. #include <vlc/vout.h>
  32. #include <vlc/decoder.h>
  33. #include "subtitle.h"
  34. #include "common.h"
  35. #include "render.h"
  36. #include "ogt.h"
  37. #ifdef HAVE_LIBPNG
  38. #include <png.h>
  39. #endif
  40. /* An image color is a two-bit palette entry: 0..3 */ 
  41. typedef uint8_t ogt_color_t;
  42. /*****************************************************************************
  43.  * Local prototypes.
  44.  *****************************************************************************/
  45. static int  ParseImage         ( decoder_t *, subpicture_t * );
  46. /*
  47.   The format is roughly as follows (everything is big-endian):
  48.  
  49.    size     description
  50.    -------------------------------------------
  51.    byte     subtitle channel (0..7) in bits 0-3 
  52.    byte     subtitle packet number of this subtitle image 0-N,
  53.             if the subtitle packet is complete, the top bit of the byte is 1.
  54.    u_int16  subtitle image number
  55.    u_int16  length in bytes of the rest
  56.    byte     option flags, unknown meaning except bit 3 (0x08) indicates
  57.       presence of the duration field
  58.    byte     unknown 
  59.    u_int32  duration in 1/90000ths of a second (optional), start time
  60.       is as indicated by the PTS in the PES header
  61.    u_int32  xpos
  62.    u_int32  ypos
  63.    u_int32  width (must be even)
  64.    u_int32  height (must be even)
  65.    byte[16] palette, 4 palette entries, each contains values for
  66.       Y, U, V and transparency, 0 standing for transparent
  67.    byte     command,
  68.       cmd>>6==1 indicates shift
  69.       (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
  70.    u_int32  shift duration in 1/90000ths of a second
  71.    u_int16  offset of odd-numbered scanlines - subtitle images are 
  72.             given in interlace order
  73.    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
  74.             2-bits per palette number
  75. */
  76. /* FIXME: do we really need p_buffer and p? 
  77.    Can't all of thes _offset's and _lengths's get removed? 
  78. */
  79. void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
  80. {
  81.   decoder_sys_t *p_sys = p_dec->p_sys;
  82.   uint8_t *p = p_buffer;
  83.   int i;
  84.   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
  85.   p_sys->i_pts    = p_block->i_pts;
  86.   p_sys->i_spu_size = GETINT16(p);
  87.   p_sys->i_options  = *p++;
  88.   p_sys->i_options2 = *p++;
  89.   
  90.   if ( p_sys->i_options & 0x08 ) {
  91.     p_sys->i_duration = GETINT32(p);
  92.     p_sys->i_duration *= config_GetInt( p_dec, MODULE_STRING 
  93.                                         "-duration-scaling" );
  94.   } else {
  95.     /* 0 means display until next subtitle comes in. */
  96.     p_sys->i_duration = 0;
  97.   }
  98.   p_sys->i_x_start= GETINT16(p);
  99.   p_sys->i_y_start= GETINT16(p);
  100.   p_sys->i_width  = GETINT16(p);
  101.   p_sys->i_height = GETINT16(p);
  102.   
  103.   for (i=0; i<4; i++) {
  104.     p_sys->p_palette[i].s.y = *p++;
  105.     p_sys->p_palette[i].s.u = *p++;
  106.     p_sys->p_palette[i].s.v = *p++;
  107.     /* OGT has 8-bit resolution for alpha, but DVD's and CVDS use 4-bits.
  108.        Since we want to use the same render routine, rather than scale up
  109.        CVD (and DVD) subtitles, we'll scale down ours. 
  110.     */
  111.     p_sys->p_palette[i].s.t = (*p++) >> 4;
  112.   }
  113.   p_sys->i_cmd = *p++;
  114.       /* We do not really know this, FIXME */
  115.   if ( p_sys->i_cmd ) {
  116.     p_sys->i_cmd_arg = GETINT32(p);
  117.   }
  118.   /* Actually, this is measured against a different origin, so we have to
  119.      adjust it */
  120.   p_sys->second_field_offset = GETINT16(p);
  121.   p_sys->i_image_offset  = p - p_buffer;
  122.   p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
  123.   p_sys->metadata_length = p_sys->i_image_offset;
  124.   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
  125.     msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
  126.      "spu size: %d, duration: %lu (d:%d p:%d)",
  127.      p_sys->i_x_start, p_sys->i_y_start, 
  128.      p_sys->i_width, p_sys->i_height, 
  129.      p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
  130.      p_sys->i_image_length, p_sys->i_image_offset);
  131.     
  132.     for (i=0; i<4; i++) {
  133.       msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
  134.        p_sys->p_palette[i].s.t, p_sys->p_palette[i].s.y, 
  135.        p_sys->p_palette[i].s.u, p_sys->p_palette[i].s.v );
  136.     }
  137.   }
  138. }
  139. /*****************************************************************************
  140.  * ParsePacket: parse an SPU packet and send it to the video output
  141.  *****************************************************************************
  142.  * This function parses the SPU packet and, if valid, sends it to the
  143.  * video output.
  144.  *****************************************************************************/
  145. void 
  146. E_(ParsePacket)( decoder_t *p_dec)
  147. {
  148.     decoder_sys_t *p_sys = p_dec->p_sys;
  149.     subpicture_t  *p_spu;
  150.     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
  151.     
  152.     /* Allocate the subpicture internal data. */
  153.     p_spu = spu_CreateSubpicture( p_sys->p_vout->p_spu );
  154.     if( p_spu == NULL ) return;
  155.     p_spu->i_channel = p_sys->i_subpic_channel;
  156.     /* In ParseImage we expand the run-length encoded color 0's; also
  157.        we expand pixels and remove the color palette. This should
  158.        facilitate scaling and antialiasing and speed up rendering.
  159.     */
  160.     p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
  161.    + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
  162.     /* Fill the p_spu structure */
  163.     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
  164.     p_spu->pf_render  = VCDSubBlend;
  165.     p_spu->pf_destroy = VCDSubDestroySPU;
  166.     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
  167.     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
  168.     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
  169.     p_spu->i_x        = p_sys->i_x_start 
  170.       + config_GetInt( p_dec, MODULE_STRING "-horizontal-correct" );
  171.     p_spu->p_sys->p_palette[0] = p_sys->p_palette[0];
  172.     p_spu->p_sys->p_palette[1] = p_sys->p_palette[1];
  173.     p_spu->p_sys->p_palette[2] = p_sys->p_palette[2];
  174.     p_spu->p_sys->p_palette[3] = p_sys->p_palette[3];
  175.     /* FIXME: use aspect ratio for x? */
  176.     p_spu->i_x        = (p_spu->i_x * 3) / 4; 
  177.     p_spu->i_y        = p_sys->i_y_start 
  178.       + config_GetInt( p_dec, MODULE_STRING "-vertical-correct" );
  179.     p_spu->i_width    = p_sys->i_width;
  180.     p_spu->i_height   = p_sys->i_height;
  181.     p_spu->i_start    = p_sys->i_pts;
  182.     p_spu->i_stop     = p_sys->i_pts + p_sys->i_duration;
  183.     
  184.     p_spu->p_sys->b_crop  = VLC_FALSE;
  185.     p_spu->p_sys->i_debug = p_sys->i_debug;
  186.     /* Get display time now. If we do it later, we may miss the PTS. */
  187.     p_spu->p_sys->i_pts = p_sys->i_pts;
  188.     /* Attach to our input thread */
  189.     p_spu->p_sys->p_input = vlc_object_find( p_dec,
  190.                                              VLC_OBJECT_INPUT, FIND_PARENT );
  191.     /* We try to display it */
  192.     if( ParseImage( p_dec, p_spu ) )
  193.     {
  194.         /* There was a parse error, delete the subpicture */
  195.         spu_DestroySubpicture( p_sys->p_vout->p_spu, p_spu );
  196.         return;
  197.     }
  198.     /* SPU is finished - we can ask the video output to display it */
  199.     spu_DisplaySubpicture( p_sys->p_vout->p_spu, p_spu );
  200. }
  201. /* Advance pointer to image pointer, update internal i_2bit_field counter
  202.    and check that we haven't goine too far  in the image data. */
  203. #define advance_color_pointer_byte
  204.   p++;
  205.   i_2bit_field=4;
  206.   if (p >= maxp) {
  207.     msg_Warn( p_dec,
  208.       "broken subtitle - tried to access beyond end "
  209.       "in image extraction");
  210.     return VLC_EGENERIC;
  211.   }
  212. #define advance_color_pointer
  213.   i_2bit_field--;
  214.   if ( i_2bit_field == 0 ) {
  215.     advance_color_pointer_byte;
  216.   }
  217. #define OGT_FIELD_BITS (2)
  218. #define OGT_FIELD_MASK  ((1<<OGT_FIELD_BITS) - 1) 
  219. /* Get the next field - either a palette index or a RLE count for
  220.    color 0.  To do this we use byte image pointer p, and i_2bit_field
  221.    which indicates where we are in the byte.
  222. */
  223. static inline ogt_color_t 
  224. ExtractField(uint8_t *p, unsigned int i_2bit_field) 
  225. {
  226.   return ( ( *p >> (OGT_FIELD_BITS*(i_2bit_field-1)) ) & OGT_FIELD_MASK );
  227. }
  228. /*****************************************************************************
  229.  * ParseImage: parse the image part of the subtitle
  230.  *****************************************************************************
  231.  This part parses the subtitle graphical data and stores it in a more
  232.  convenient structure for later rendering. 
  233.  The image is encoded using two bits per pixel that select a palette
  234.  entry except that value 0 starts a limited run-length encoding for
  235.  color 0.  When 0 is seen, the next two bits encode one less than the
  236.  number of pixels, so we can encode run lengths from 1 to 4. These get
  237.  filled with the color in palette entry 0.
  238.  The encoding of each line is padded to a whole number of bytes.  The
  239.  first field is padded to an even byte length and the complete subtitle
  240.  is padded to a 4-byte multiple that always include one zero byte at
  241.  the end.
  242.  However we'll transform this so that that the RLE is expanded and
  243.  interlacing will also be removed. On output each pixel entry will by
  244.  an 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
  245.  *****************************************************************************/
  246. static int 
  247. ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
  248. {
  249.     decoder_sys_t *p_sys = p_dec->p_sys;
  250.     unsigned int i_field;  /* The subtitles are interlaced, are we on an
  251.       even or odd scanline?  */
  252.     unsigned int i_row;    /* scanline row number */
  253.     unsigned int i_column; /* scanline column number */
  254.     unsigned int i_width  = p_sys->i_width;
  255.     unsigned int i_height = p_sys->i_height;
  256.     uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
  257.     uint8_t i_2bit_field;           /* The 2-bit field to sue in byte of *p.
  258.        Has value 0..4. */
  259.     uint8_t i_pending_zero = 0;    /* number of pixels to fill with 
  260.       color zero 0..3 */
  261.     ogt_color_t i_color;           /* current pixel color: 0..3 */
  262.     uint8_t *p = p_sys->subtitle_data  + p_sys->i_image_offset;
  263.     uint8_t *maxp = p + p_sys->i_image_length;
  264.     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
  265.        i_width, i_height);
  266.     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
  267.       printf("n");
  268.     for ( i_field=0; i_field < 2; i_field++ ) {
  269.       i_2bit_field = 4;
  270.       for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
  271. for ( i_column=0; i_column<i_width; i_column++ ) {
  272.   if ( i_pending_zero ) {
  273.     /* We are in the middle of a RLE expansion, just decrement and 
  274.        fall through with current color value */
  275.     i_pending_zero--;
  276.     i_color = 0;
  277.   } else {
  278.     i_color = ExtractField( p, i_2bit_field );
  279.     advance_color_pointer;
  280.     if ( i_color == 0 ) {
  281.       i_pending_zero = ExtractField( p, i_2bit_field );
  282.       advance_color_pointer;
  283.       /* Fall through with i_color == 0 to output the first cell */
  284.     }
  285.   }
  286.   /* Color is 0-3. */
  287.   p_dest[i_row*i_width+i_column] = i_color;
  288.   if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
  289.     printf("%1d", i_color);
  290. }
  291. if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE))
  292.   printf("n");
  293. if ( i_2bit_field != 4 ) {
  294.   /* Lines are padded to complete bytes, ignore padding */
  295.   advance_color_pointer_byte;
  296. }
  297.       }
  298.       p = p_sys->subtitle_data + p_sys->i_image_offset 
  299. + p_sys->second_field_offset;
  300.     }
  301.     if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
  302.       /* Dump out image not interlaced... */
  303.       VCDSubDumpImage( p_dest, i_height, i_width );
  304.     }
  305. #ifdef HAVE_LIBPNG
  306.     if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
  307. #define TEXT_COUNT 2
  308.       /* Dump image to a file in PNG format. */
  309.       char filename[300];
  310.       png_text text_ptr[TEXT_COUNT];
  311.       text_ptr[0].key = "Preparer";
  312.       text_ptr[0].text = "VLC";
  313.       text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
  314.       text_ptr[1].key = "Description";
  315.       text_ptr[1].text = "SVCD Subtitle";
  316.       text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
  317.       snprintf(filename, 300, "%s%d.png", "/tmp/vlc-svcd-sub", p_sys->i_image);
  318.       VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
  319.      text_ptr, TEXT_COUNT );
  320.     }
  321. #endif /*HAVE_LIBPNG*/
  322.     
  323.     VCDSubHandleScaling( p_spu, p_dec );
  324.     return VLC_SUCCESS;
  325. }
  326. /* 
  327.  * Local variables:
  328.  *  c-file-style: "gnu"
  329.  *  tab-width: 8
  330.  *  indent-tabs-mode: nil
  331.  * End:
  332.  */