Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

nsc.c

00001 /*****************************************************************************
00002  * nsc.c: NSC file demux and encoding decoder
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * $Id: nsc.c 12923 2005-10-23 09:25:27Z courmisch $
00006  *
00007  * Authors: Jon Lech Johansen <[email protected]>
00008  *          Derk-Jan Hartman <hartman at videolan dot org>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <stdlib.h>                                      /* malloc(), free() */
00029 #include <ctype.h>
00030 #include <vlc/vlc.h>
00031 #include <vlc/input.h>
00032 #include <vlc_playlist.h>
00033 
00034 #define MAX_LINE 16024
00035 
00036 /*****************************************************************************
00037  * Module descriptor
00038  *****************************************************************************/
00039 static int  DemuxOpen  ( vlc_object_t * );
00040 static void DemuxClose ( vlc_object_t * );
00041 
00042 vlc_module_begin();
00043     set_description( _("Windows Media NSC metademux") );
00044     set_category( CAT_INPUT );
00045     set_subcategory( SUBCAT_INPUT_DEMUX );
00046     set_capability( "demux2", 2 );
00047     set_callbacks( DemuxOpen, DemuxClose );
00048 vlc_module_end();
00049 
00050 static int Demux ( demux_t *p_demux );
00051 static int Control( demux_t *p_demux, int i_query, va_list args );
00052 
00053 static const unsigned char inverse[ 128 ] =
00054 {
00055     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00056     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00057     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00058     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00059     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
00060     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
00061     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
00062     0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
00063     0xFF, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
00064     0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
00065     0x3B, 0x3C, 0x3D, 0x3E, 0xFF, 0x3F, 0xFF, 0xFF
00066 };
00067 
00068 static int load_byte( unsigned char encoding_type,
00069                       unsigned char *output, char **input,
00070                       unsigned char *j, unsigned char *k )
00071 {
00072     *output = 0;
00073 
00074     if( encoding_type == 1 )
00075     {
00076         if( isxdigit( **input ) == 0 )
00077             return -1;
00078 
00079         if( isdigit( **input ) == 0 )
00080             *output = (toupper( **input ) - 7) * 16;
00081         else
00082             *output = **input * 16;
00083 
00084         (*input)++;
00085 
00086         if( isxdigit( **input ) == 0 )
00087             return -1;
00088 
00089         if( isdigit( **input ) == 0 )
00090             *output |= toupper( **input ) - 0x37;
00091         else
00092             *output |= **input - 0x30;
00093 
00094         (*input)++;
00095     }
00096     else if( encoding_type == 2 )
00097     {
00098         unsigned char **uinput = (unsigned char **)input;
00099 
00100         if( **uinput > 127 || inverse[ **uinput ] == 0xFF )
00101             return -1;
00102 
00103         if( *k == 0 )
00104         {
00105             if( (*uinput)[ 1 ] > 127 || inverse[ (*uinput)[ 1 ] ] == 0xFF )
00106                 return -1;
00107 
00108             *output = (inverse[ (*uinput)[ 0 ] ] * 4) |
00109                         (inverse[ (*uinput)[ 1 ] ] / 16);
00110 
00111             *j = inverse[ (*uinput)[ 1 ] ] * 16;
00112             *k = 4;
00113 
00114             (*uinput) += 2;
00115         }
00116         else if( *k == 2 )
00117         {
00118             *output = *j | inverse[ **uinput ];
00119 
00120             *j = 0;
00121             *k = 0;
00122 
00123             (*uinput)++;
00124         }
00125         else if( *k == 4 )
00126         {
00127             *output = (inverse[ **uinput ] / 4) | *j;
00128 
00129             *j = inverse[ **uinput ] * 64;
00130             *k = 2;
00131 
00132             (*uinput)++;
00133         }
00134     }
00135 
00136     return 0;
00137 }
00138 
00139 char *nscdec( vlc_object_t *p_demux, char* p_encoded )
00140 {
00141     unsigned int i;
00142     unsigned char tmp;
00143     unsigned char j, k;
00144     unsigned int length;
00145     unsigned char encoding_type;
00146 
00147     vlc_iconv_t conv;
00148     size_t buf16_size;
00149     unsigned char *buf16;
00150     char *p_buf16;
00151     size_t buf8_size;
00152     char *buf8;
00153     char *p_buf8;
00154 
00155     char *p_input = p_encoded;
00156 
00157     if( strlen( p_input ) < 15 )
00158     {
00159         msg_Err( p_demux, "input string less than 15 characters" );
00160         return NULL;
00161     }
00162 
00163     if( load_byte( 1, &encoding_type, &p_input, NULL, NULL ) )
00164     {
00165         msg_Err( p_demux, "unable to get NSC encoding type" );
00166         return NULL;
00167     }
00168 
00169     if( encoding_type != 1 && encoding_type != 2 )
00170     {
00171         msg_Err( p_demux, "encoding type %d is not supported",
00172                  encoding_type );
00173         return NULL;
00174     }
00175 
00176     j = k = 0;
00177 
00178     if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
00179     {
00180         msg_Err( p_demux, "load_byte failed" );
00181         return NULL;
00182     }
00183 
00184     for( i = 0; i < 4; i++ )
00185     {
00186         if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
00187         {
00188             msg_Err( p_demux, "load_byte failed" );
00189             return NULL;
00190         }
00191     }
00192 
00193     length = 0;
00194     for( i = 4; i; i-- )
00195     {
00196         if( load_byte( encoding_type, &tmp, &p_input, &j, &k ) )
00197         {
00198             msg_Err( p_demux, "load_byte failed" );
00199             return NULL;
00200         }
00201         length |= tmp << ((i - 1) * 8);
00202     }
00203 
00204     if( length == 0 )
00205     {
00206         msg_Err( p_demux, "Length is 0" );
00207         return NULL;
00208     }
00209 
00210     buf16_size = length;
00211     buf16 = (unsigned char *)malloc( buf16_size );
00212     if( buf16 == NULL )
00213     {
00214         msg_Err( p_demux, "Out of memory" );
00215         return NULL;
00216     }
00217 
00218     for( i = 0; i < length; i++ )
00219     {
00220         if( load_byte( encoding_type, &buf16[ i ], &p_input, &j, &k ) )
00221         {
00222             msg_Err( p_demux, "load_byte failed" );
00223             free( (void *)buf16 );
00224             return NULL;
00225         }
00226     }
00227 
00228     buf8_size = length;
00229     buf8 = (char *)malloc( buf8_size + 1 );
00230     if( buf8 == NULL )
00231     {
00232         msg_Err( p_demux, "Out of memory" );
00233         free( (void *)buf16 );
00234         return NULL;
00235     }
00236 
00237     conv = vlc_iconv_open( "UTF-8", "UTF-16LE" );
00238     if( conv == (vlc_iconv_t)-1 )
00239     {
00240         msg_Err( p_demux, "iconv_open failed" );
00241         free( (void *)buf16 );
00242         free( (void *)buf8 );
00243         return NULL;
00244     }
00245 
00246     p_buf8 = &buf8[ 0 ];
00247     p_buf16 = (char *)&buf16[ 0 ];
00248 
00249     if( vlc_iconv( conv, &p_buf16, &buf16_size, &p_buf8, &buf8_size ) < 0 )
00250     {
00251         msg_Err( p_demux, "iconv failed" );
00252         return NULL;
00253     }
00254     else
00255     {
00256         buf8[ length - buf8_size ] = '\0';
00257     }
00258 
00259     vlc_iconv_close( conv );
00260 
00261     free( (void *)buf16 );
00262     return buf8;
00263 }
00264 
00265 static int DemuxOpen( vlc_object_t * p_this )
00266 {
00267     demux_t *p_demux = (demux_t *)p_this;
00268     byte_t *p_peek;
00269     int i_size;
00270 
00271     /* Lets check the content to see if this is a NSC file */
00272     i_size = stream_Peek( p_demux->s, &p_peek, MAX_LINE );
00273     i_size -= sizeof("NSC Format Version=") - 1;
00274 
00275     if ( i_size > 0 )
00276     {
00277         while ( i_size && strncasecmp( p_peek, "NSC Format Version=",
00278                                        (int) sizeof("NSC Format Version=") - 1 ) )
00279         {
00280             p_peek++;
00281             i_size--;
00282         }
00283         if ( !strncasecmp( p_peek, "NSC Format Version=",
00284                            (int) sizeof("NSC Format Version=") -1 ) )
00285         {
00286             p_demux->pf_demux = Demux;
00287             p_demux->pf_control = Control;
00288             return VLC_SUCCESS;
00289         }
00290     }
00291     return VLC_EGENERIC;
00292 }
00293 
00294 
00295 /*****************************************************************************
00296  * Deactivate: frees unused data
00297  *****************************************************************************/
00298 static void DemuxClose( vlc_object_t *p_this )
00299 {
00300     return;
00301 }
00302 
00303 static int ParseLine ( demux_t *p_demux, char *psz_line )
00304 {
00305     char        *psz_bol;
00306     char        *psz_value;
00307 
00308     psz_bol = psz_line;
00309     /* Remove unnecessary tabs or spaces at the beginning of line */
00310     while( *psz_bol == ' ' || *psz_bol == '\t' ||
00311            *psz_bol == '\n' || *psz_bol == '\r' )
00312     {
00313         psz_bol++;
00314     }
00315     psz_value = strchr( psz_bol, '=' );
00316     if( psz_value == NULL )
00317     {
00318         return 0; /* a [Address] or [Formats] line or something else we will ignore */
00319     }
00320     *psz_value = '\0';
00321     psz_value++;
00322     
00323     if( !strncasecmp( psz_value, "0x", 2 ) )
00324     {
00325         int i_value;
00326         sscanf( psz_value, "%x", &i_value );
00327         msg_Dbg( p_demux, "%s = %d", psz_bol, i_value );
00328     }
00329     else if( !strncasecmp( psz_bol, "Format", 6 ) )
00330     {
00331         msg_Dbg( p_demux, "%s = asf header", psz_bol );
00332     }
00333     else
00334     {
00335         /* This should be NSC encoded strings in the values */
00336         char *psz_out;
00337         psz_out = nscdec( (vlc_object_t *)p_demux, psz_value );
00338         if( psz_out )
00339         {
00340             msg_Dbg( p_demux, "%s = %s", psz_bol, psz_out );
00341             if( psz_out) free( psz_out );
00342         }
00343     }
00344     return VLC_SUCCESS;
00345 }
00346 
00347 /*****************************************************************************
00348  * Demux: reads and demuxes data packets
00349  *****************************************************************************
00350  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
00351  *****************************************************************************/
00352 static int Demux ( demux_t *p_demux )
00353 {
00354     char            *psz_line;
00355 
00356     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
00357     {
00358         ParseLine( p_demux, psz_line );
00359         if( psz_line ) free( psz_line );
00360     }
00361     return VLC_SUCCESS;
00362 }
00363 
00364 static int Control( demux_t *p_demux, int i_query, va_list args )
00365 {
00366     return VLC_EGENERIC;
00367 }

Generated on Tue Dec 20 10:14:35 2005 for vlc-0.8.4a by  doxygen 1.4.2