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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * nsc.c: NSC file demux and encoding decoder
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * $Id: c401c0b5f2a6c3a4ea67a031b89a1f1b14873539 $
  6.  *
  7.  * Authors: Jon Lech Johansen <jon@nanocrew.net>
  8.  *          Derk-Jan Hartman <hartman at videolan dot org>
  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_demux.h>
  33. #include <ctype.h>
  34. #define MAX_LINE 16024
  35. /*****************************************************************************
  36.  * Module descriptor
  37.  *****************************************************************************/
  38. static int  DemuxOpen  ( vlc_object_t * );
  39. static void DemuxClose ( vlc_object_t * );
  40. vlc_module_begin ()
  41.     set_description( N_("Windows Media NSC metademux") )
  42.     set_category( CAT_INPUT )
  43.     set_subcategory( SUBCAT_INPUT_DEMUX )
  44.     set_capability( "demux", 3 )
  45.     set_callbacks( DemuxOpen, DemuxClose )
  46. vlc_module_end ()
  47. static int Demux ( demux_t *p_demux );
  48. static int Control( demux_t *p_demux, int i_query, va_list args );
  49. static const unsigned char inverse[ 128 ] =
  50. {
  51.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  52.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  53.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  54.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  55.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
  56.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
  57.     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
  58.     0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  59.     0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
  60.     0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
  61.     0x3B, 0x3C, 0x3D, 0x3E, 0xFF, 0x3F, 0xFF, 0xFF
  62. };
  63. static int load_byte( unsigned char encoding_type,
  64.                       unsigned char *output, char **input,
  65.                       unsigned char *j, unsigned char *k )
  66. {
  67.     *output = 0;
  68.     if( encoding_type == 1 )
  69.     {
  70.         if( isxdigit( **input ) == 0 )
  71.             return -1;
  72.         if( isdigit( **input ) == 0 )
  73.             *output = (toupper( **input ) - 7) * 16;
  74.         else
  75.             *output = **input * 16;
  76.         (*input)++;
  77.         if( isxdigit( **input ) == 0 )
  78.             return -1;
  79.         if( isdigit( **input ) == 0 )
  80.             *output |= toupper( **input ) - 0x37;
  81.         else
  82.             *output |= **input - 0x30;
  83.         (*input)++;
  84.     }
  85.     else if( encoding_type == 2 )
  86.     {
  87.         unsigned char **uinput = (unsigned char **)input;
  88.         if( **uinput > 127 || inverse[ **uinput ] == 0xFF )
  89.             return -1;
  90.         if( *k == 0 )
  91.         {
  92.             if( (*uinput)[ 1 ] > 127 || inverse[ (*uinput)[ 1 ] ] == 0xFF )
  93.                 return -1;
  94.             *output = (inverse[ (*uinput)[ 0 ] ] * 4) |
  95.                         (inverse[ (*uinput)[ 1 ] ] / 16);
  96.             *j = inverse[ (*uinput)[ 1 ] ] * 16;
  97.             *k = 4;
  98.             (*uinput) += 2;
  99.         }
  100.         else if( *k == 2 )
  101.         {
  102.             *output = *j | inverse[ **uinput ];
  103.             *j = 0;
  104.             *k = 0;
  105.             (*uinput)++;
  106.         }
  107.         else if( *k == 4 )
  108.         {
  109.             *output = (inverse[ **uinput ] / 4) | *j;
  110.             *j = inverse[ **uinput ] * 64;
  111.             *k = 2;
  112.             (*uinput)++;
  113.         }
  114.     }
  115.     return 0;
  116. }
  117. static char *nscdec( vlc_object_t *p_demux, char* p_encoded )
  118. {
  119.     unsigned int i;
  120.     unsigned char tmp;
  121.     unsigned char j, k;
  122.     unsigned int length;
  123.     unsigned char encoding_type;
  124.     vlc_iconv_t conv;
  125.     size_t buf16_size;
  126.     unsigned char *buf16;
  127.     const char *p_buf16;
  128.     size_t buf8_size;
  129.     char *buf8;
  130.     char *p_buf8;
  131.     char *p_input = p_encoded;
  132.     if( strlen( p_input ) < 15 )
  133.     {
  134.         msg_Err( p_demux, "input string less than 15 characters" );
  135.         return NULL;
  136.     }
  137.     if( load_byte( 1, &encoding_type, &p_input, NULL, NULL ) )
  138.     {
  139.         msg_Err( p_demux, "unable to get NSC encoding type" );
  140.         return NULL;
  141.     }
  142.     if( encoding_type != 1 && encoding_type != 2 )
  143.     {
  144.         msg_Err( p_demux, "encoding type %d is not supported",
  145.                  encoding_type );
  146.         return NULL;
  147.     }
  148.     j = k = 0;
  149.     if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
  150.     {
  151.         msg_Err( p_demux, "load_byte failed" );
  152.         return NULL;
  153.     }
  154.     for( i = 0; i < 4; i++ )
  155.     {
  156.         if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
  157.         {
  158.             msg_Err( p_demux, "load_byte failed" );
  159.             return NULL;
  160.         }
  161.     }
  162.     length = 0;
  163.     for( i = 4; i; i-- )
  164.     {
  165.         if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
  166.         {
  167.             msg_Err( p_demux, "load_byte failed" );
  168.             return NULL;
  169.         }
  170.         length |= tmp << ((i - 1) * 8);
  171.     }
  172.     if( length == 0 )
  173.     {
  174.         msg_Err( p_demux, "Length is 0" );
  175.         return NULL;
  176.     }
  177.     buf16_size = length;
  178.     buf16 = malloc( buf16_size );
  179.     if( buf16 == NULL )
  180.         return NULL;
  181.     for( i = 0; i < length; i++ )
  182.     {
  183.         if( load_byte( encoding_type, &buf16[ i ], &p_input, &j, &k ) )
  184.         {
  185.             msg_Err( p_demux, "load_byte failed" );
  186.             free( buf16 );
  187.             return NULL;
  188.         }
  189.     }
  190.     buf8_size = length;
  191.     buf8 = malloc( buf8_size + 1 );
  192.     if( buf8 == NULL )
  193.     {
  194.         free( buf16 );
  195.         return NULL;
  196.     }
  197.     conv = vlc_iconv_open( "UTF-8", "UTF-16LE" );
  198.     if( conv == (vlc_iconv_t)(-1) )
  199.     {
  200.         msg_Err( p_demux, "iconv_open failed" );
  201.         free( buf16 );
  202.         free( buf8 );
  203.         return NULL;
  204.     }
  205.     p_buf8 = buf8;
  206.     p_buf16 = (const char *)buf16;
  207.     if( vlc_iconv( conv, &p_buf16, &buf16_size, &p_buf8, &buf8_size ) == (size_t)(-1) )
  208.     {
  209.         msg_Err( p_demux, "iconv failed" );
  210.         return NULL;
  211.     }
  212.     else
  213.     {
  214.         buf8[ length - buf8_size ] = '';
  215.     }
  216.     vlc_iconv_close( conv );
  217.     free( buf16 );
  218.     return buf8;
  219. }
  220. static int DemuxOpen( vlc_object_t * p_this )
  221. {
  222.     demux_t *p_demux = (demux_t *)p_this;
  223.     const uint8_t *p_peek;
  224.     int i_size;
  225.     /* Lets check the content to see if this is a NSC file */
  226.     i_size = stream_Peek( p_demux->s, &p_peek, MAX_LINE );
  227.     i_size -= sizeof("NSC Format Version=") - 1;
  228.     if ( i_size > 0 )
  229.     {
  230.         while ( i_size && strncasecmp( (char *)p_peek, "NSC Format Version=",
  231.                                        (int) sizeof("NSC Format Version=") - 1 ) )
  232.         {
  233.             p_peek++;
  234.             i_size--;
  235.         }
  236.         if ( !strncasecmp( (char *)p_peek, "NSC Format Version=",
  237.                            (int) sizeof("NSC Format Version=") -1 ) )
  238.         {
  239.             p_demux->pf_demux = Demux;
  240.             p_demux->pf_control = Control;
  241.             return VLC_SUCCESS;
  242.         }
  243.     }
  244.     return VLC_EGENERIC;
  245. }
  246. /*****************************************************************************
  247.  * Deactivate: frees unused data
  248.  *****************************************************************************/
  249. static void DemuxClose( vlc_object_t *p_this )
  250. {
  251.     return;
  252. }
  253. static int ParseLine ( demux_t *p_demux, char *psz_line )
  254. {
  255.     char        *psz_bol;
  256.     char        *psz_value;
  257.     psz_bol = psz_line;
  258.     /* Remove unnecessary tabs or spaces at the beginning of line */
  259.     while( *psz_bol == ' ' || *psz_bol == 't' ||
  260.            *psz_bol == 'n' || *psz_bol == 'r' )
  261.     {
  262.         psz_bol++;
  263.     }
  264.     psz_value = strchr( psz_bol, '=' );
  265.     if( psz_value == NULL )
  266.     {
  267.         return 0; /* a [Address] or [Formats] line or something else we will ignore */
  268.     }
  269.     *psz_value = '';
  270.     psz_value++;
  271.  
  272.     if( !strncasecmp( psz_value, "0x", 2 ) )
  273.     {
  274.         int i_value;
  275.         sscanf( psz_value, "%x", &i_value );
  276.         msg_Dbg( p_demux, "%s = %d", psz_bol, i_value );
  277.     }
  278.     else if( !strncasecmp( psz_bol, "Format", 6 ) )
  279.     {
  280.         msg_Dbg( p_demux, "%s = asf header", psz_bol );
  281.     }
  282.     else
  283.     {
  284.         /* This should be NSC encoded strings in the values */
  285.         char *psz_out;
  286.         psz_out = nscdec( (vlc_object_t *)p_demux, psz_value );
  287.         if( psz_out )
  288.         {
  289.             msg_Dbg( p_demux, "%s = %s", psz_bol, psz_out );
  290.             free( psz_out );
  291.         }
  292.     }
  293.     return VLC_SUCCESS;
  294. }
  295. /*****************************************************************************
  296.  * Demux: reads and demuxes data packets
  297.  *****************************************************************************
  298.  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  299.  *****************************************************************************/
  300. static int Demux ( demux_t *p_demux )
  301. {
  302.     char            *psz_line;
  303.     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
  304.     {
  305.         ParseLine( p_demux, psz_line );
  306.         free( psz_line );
  307.     }
  308.     return VLC_SUCCESS;
  309. }
  310. static int Control( demux_t *p_demux, int i_query, va_list args )
  311. {
  312.     return VLC_EGENERIC;
  313. }