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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * nsv.c: NullSoft Video demuxer.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: nsv.c 7232 2004-04-01 23:21:13Z fenrir $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <vlc/vlc.h>
  28. #include <vlc/input.h>
  29. /* TODO:
  30.  *  - implement NSVf parsing (to get meta data)
  31.  *  - implement missing Control (and in the right way)
  32.  *  - ...
  33.  */
  34. /*****************************************************************************
  35.  * Module descriptor
  36.  *****************************************************************************/
  37. static int  Open    ( vlc_object_t * );
  38. static void Close  ( vlc_object_t * );
  39. vlc_module_begin();
  40.     set_description( _("NullSoft demuxer" ) );
  41.     set_capability( "demux2", 10 );
  42.     set_callbacks( Open, Close );
  43.     add_shortcut( "nsv" );
  44. vlc_module_end();
  45. /*****************************************************************************
  46.  * Local prototypes
  47.  *****************************************************************************/
  48. struct demux_sys_t
  49. {
  50.     es_format_t  fmt_audio;
  51.     es_out_id_t *p_audio;
  52.     es_format_t  fmt_video;
  53.     es_out_id_t *p_video;
  54.     es_format_t  fmt_sub;
  55.     es_out_id_t  *p_sub;
  56.     int64_t     i_pcr;
  57.     int64_t     i_time;
  58.     int64_t     i_pcr_inc;
  59. };
  60. static int Demux  ( demux_t *p_demux );
  61. static int Control( demux_t *p_demux, int i_query, va_list args );
  62. static int ReSynch( demux_t *p_demux );
  63. static int ReadNSVf( demux_t *p_demux );
  64. static int ReadNSVs( demux_t *p_demux );
  65. /*****************************************************************************
  66.  * Open
  67.  *****************************************************************************/
  68. static int Open( vlc_object_t *p_this )
  69. {
  70.     demux_t     *p_demux = (demux_t*)p_this;
  71.     demux_sys_t *p_sys;
  72.     uint8_t     *p_peek;
  73.     if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
  74.     {
  75.         msg_Err( p_demux, "cannot peek" );
  76.         return VLC_EGENERIC;
  77.     }
  78.     if( strncmp( p_peek, "NSVf", 4 ) && strncmp( p_peek, "NSVs", 4 ))
  79.     {
  80.        /* In case we had force this demuxer we try to resynch */
  81.         if( strcmp( p_demux->psz_demux, "nsv" ) || ReSynch( p_demux ) )
  82.         {
  83.             msg_Warn( p_demux, "NSV module discarded" );
  84.             return VLC_EGENERIC;
  85.         }
  86.     }
  87.     /* Fill p_demux field */
  88.     p_demux->pf_demux = Demux;
  89.     p_demux->pf_control = Control;
  90.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  91.     es_format_Init( &p_sys->fmt_audio, AUDIO_ES, 0 );
  92.     p_sys->p_audio = NULL;
  93.     es_format_Init( &p_sys->fmt_video, VIDEO_ES, 0 );
  94.     p_sys->p_video = NULL;
  95.     es_format_Init( &p_sys->fmt_sub, SPU_ES, 0 );
  96.     p_sys->p_sub = NULL;
  97.     p_sys->i_pcr   = 1;
  98.     p_sys->i_time  = 0;
  99.     p_sys->i_pcr_inc = 0;
  100.     return VLC_SUCCESS;
  101. }
  102. /*****************************************************************************
  103.  * Close
  104.  *****************************************************************************/
  105. static void Close( vlc_object_t *p_this )
  106. {
  107.     demux_t     *p_demux = (demux_t*)p_this;
  108.     demux_sys_t *p_sys = p_demux->p_sys;
  109.     free( p_sys );
  110. }
  111. /*****************************************************************************
  112.  * Demux:
  113.  *****************************************************************************/
  114. static int Demux( demux_t *p_demux )
  115. {
  116.     demux_sys_t *p_sys = p_demux->p_sys;
  117.     uint8_t     header[5];
  118.     uint8_t     *p_peek;
  119.     int         i_size;
  120.     block_t     *p_frame;
  121.     for( ;; )
  122.     {
  123.         if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
  124.         {
  125.             msg_Warn( p_demux, "cannot peek" );
  126.             return 0;
  127.         }
  128.         if( !strncmp( p_peek, "NSVf", 4 ) )
  129.         {
  130.             if( ReadNSVf( p_demux ) )
  131.             {
  132.                 return -1;
  133.             }
  134.         }
  135.         else if( !strncmp( p_peek, "NSVs", 4 ) )
  136.         {
  137.             if( ReadNSVs( p_demux ) )
  138.             {
  139.                 return -1;
  140.             }
  141.             break;
  142.         }
  143.         else if( GetWLE( p_peek ) == 0xbeef )
  144.         {
  145.             /* Next frame of the current NSVs chunk */
  146.             if( stream_Read( p_demux->s, NULL, 2 ) < 2 )
  147.             {
  148.                 msg_Warn( p_demux, "cannot read" );
  149.                 return 0;
  150.             }
  151.             break;
  152.         }
  153.         else
  154.         {
  155.             msg_Err( p_demux, "invalid signature 0x%x (%4.4s)", *(uint32_t*)p_peek, (char*)p_peek );
  156.             if( ReSynch( p_demux ) )
  157.             {
  158.                 return -1;
  159.             }
  160.         }
  161.     }
  162.     if( stream_Read( p_demux->s, header, 5 ) < 5 )
  163.     {
  164.         msg_Warn( p_demux, "cannot read" );
  165.         return 0;
  166.     }
  167.     /* Set PCR */
  168.     es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  169.     /* Read video */
  170.     i_size = ( header[0] >> 4 ) | ( header[1] << 4 ) | ( header[2] << 12 );
  171.     if( i_size > 0 )
  172.     {
  173.         /* extra data ? */
  174.         if( (header[0]&0x0f) != 0x0 )
  175.         {
  176.             uint8_t      aux[6];
  177.             int          i_aux;
  178.             vlc_fourcc_t fcc;
  179.             if( stream_Read( p_demux->s, aux, 6 ) < 6 )
  180.             {
  181.                 msg_Warn( p_demux, "cannot read" );
  182.                 return 0;
  183.             }
  184.             i_aux = GetWLE( aux );
  185.             fcc   = VLC_FOURCC( aux[2], aux[3], aux[4], aux[5] );
  186.             msg_Dbg( p_demux, "Belekas: %d - size=%d fcc=%4.4s",
  187.                      header[0]&0xf, i_aux, (char*)&fcc );
  188.             if( fcc == VLC_FOURCC( 'S', 'U', 'B', 'T' ) && i_aux > 2 )
  189.             {
  190.                 if( p_sys->p_sub == NULL )
  191.                 {
  192.                     p_sys->fmt_sub.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
  193.                     p_sys->p_sub = es_out_Add( p_demux->out, &p_sys->fmt_sub );
  194.                     es_out_Control( p_demux->out, ES_OUT_SET_ES, p_sys->p_sub );
  195.                 }
  196.                 stream_Read( p_demux->s, NULL, 2 );
  197.                 if( ( p_frame = stream_Block( p_demux->s, i_aux - 2 ) ) )
  198.                 {
  199.                     uint8_t *p = p_frame->p_buffer;
  200.                     while( p < &p_frame->p_buffer[p_frame->i_buffer] && *p != 0 )
  201.                     {
  202.                         p++;
  203.                     }
  204.                     if( *p == 0 && p + 1 < &p_frame->p_buffer[p_frame->i_buffer] )
  205.                     {
  206.                         p_frame->i_buffer -= p + 1 - p_frame->p_buffer;
  207.                         p_frame->p_buffer = p + 1;
  208.                     }
  209.                     /* Skip the first part (it is the language name) */
  210.                     p_frame->i_pts = p_sys->i_pcr;
  211.                     p_frame->i_dts = p_sys->i_pcr + 4000000;    /* 4s */
  212.                     es_out_Send( p_demux->out, p_sys->p_sub, p_frame );
  213.                 }
  214.             }
  215.             else
  216.             {
  217.                 /* We skip this extra data */
  218.                 if( stream_Read( p_demux->s, NULL, i_aux ) < i_aux )
  219.                 {
  220.                     msg_Warn( p_demux, "cannot read" );
  221.                     return 0;
  222.                 }
  223.             }
  224.             i_size -= 6 + i_aux;
  225.         }
  226.         /* msg_Dbg( p_demux, "frame video size=%d", i_size ); */
  227.         if( i_size > 0 && ( p_frame = stream_Block( p_demux->s, i_size ) ) )
  228.         {
  229.             p_frame->i_dts = p_sys->i_pcr;
  230.             es_out_Send( p_demux->out, p_sys->p_video, p_frame );
  231.         }
  232.     }
  233.     /* Read audio */
  234.     i_size = header[3] | ( header[4] << 8 );
  235.     if( i_size > 0 )
  236.     {
  237.         /* msg_Dbg( p_demux, "frame audio size=%d", i_size ); */
  238.         if( p_sys->fmt_audio.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
  239.         {
  240.             uint8_t h[4];
  241.             stream_Read( p_demux->s, h, 4 );
  242.             p_sys->fmt_audio.audio.i_channels = h[1];
  243.             p_sys->fmt_audio.audio.i_rate = GetWLE( &h[2] );
  244.             i_size -= 4;
  245.         }
  246.         if( p_sys->p_audio == NULL )
  247.         {
  248.             p_sys->p_audio = es_out_Add( p_demux->out, &p_sys->fmt_audio );
  249.         }
  250.         if( ( p_frame = stream_Block( p_demux->s, i_size ) ) )
  251.         {
  252.             p_frame->i_dts =
  253.             p_frame->i_pts = p_sys->i_pcr;
  254.             es_out_Send( p_demux->out, p_sys->p_audio, p_frame );
  255.         }
  256.     }
  257.     p_sys->i_pcr += p_sys->i_pcr_inc;
  258.     if( p_sys->i_time >= 0 )
  259.     {
  260.         p_sys->i_time += p_sys->i_pcr_inc;
  261.     }
  262.     return 1;
  263. }
  264. /*****************************************************************************
  265.  * Control:
  266.  *****************************************************************************/
  267. static int Control( demux_t *p_demux, int i_query, va_list args )
  268. {
  269.     demux_sys_t *p_sys = p_demux->p_sys;
  270.     double f, *pf;
  271.     int64_t i64, *pi64;
  272.     switch( i_query )
  273.     {
  274.         case DEMUX_GET_POSITION:
  275.             pf = (double*) va_arg( args, double* );
  276.             i64 = stream_Size( p_demux->s );
  277.             if( i64 > 0 )
  278.             {
  279.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  280.             }
  281.             else
  282.             {
  283.                 *pf = 0.0;
  284.             }
  285.             return VLC_SUCCESS;
  286.         case DEMUX_SET_POSITION:
  287.             f = (double) va_arg( args, double );
  288.             i64 = stream_Size( p_demux->s );
  289.             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  290.             if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) || ReSynch( p_demux ) )
  291.             {
  292.                 return VLC_EGENERIC;
  293.             }
  294.             p_sys->i_time = -1; /* Invalidate time display */
  295.             return VLC_SUCCESS;
  296.         case DEMUX_GET_TIME:
  297.             pi64 = (int64_t*)va_arg( args, int64_t * );
  298.             if( p_sys->i_time < 0 )
  299.             {
  300.                 *pi64 = 0;
  301.                 return VLC_EGENERIC;
  302.             }
  303.             *pi64 = p_sys->i_time;
  304.             return VLC_SUCCESS;
  305. #if 0
  306.         case DEMUX_GET_LENGTH:
  307.             pi64 = (int64_t*)va_arg( args, int64_t * );
  308.             if( p_sys->i_mux_rate > 0 )
  309.             {
  310.                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
  311.                 return VLC_SUCCESS;
  312.             }
  313.             *pi64 = 0;
  314.             return VLC_EGENERIC;
  315. #endif
  316.         case DEMUX_GET_FPS:
  317.             pf = (double*)va_arg( args, double * );
  318.             *pf = (double)1000000.0 / (double)p_sys->i_pcr_inc;
  319.             return VLC_SUCCESS;
  320.         case DEMUX_SET_TIME:
  321.         default:
  322.             return VLC_EGENERIC;
  323.     }
  324. }
  325. /*****************************************************************************
  326.  * ReSynch:
  327.  *****************************************************************************/
  328. static int ReSynch( demux_t *p_demux )
  329. {
  330.     uint8_t *p_peek;
  331.     int      i_skip;
  332.     int      i_peek;
  333.     while( !p_demux->b_die )
  334.     {
  335.         if( ( i_peek = stream_Peek( p_demux->s, &p_peek, 1024 ) ) < 8 )
  336.         {
  337.             return VLC_EGENERIC;
  338.         }
  339.         i_skip = 0;
  340.         while( i_skip < i_peek - 4 )
  341.         {
  342.             if( !strncmp( p_peek, "NSVf", 4 ) || !strncmp( p_peek, "NSVs", 4 ) )
  343.             {
  344.                 if( i_skip > 0 )
  345.                 {
  346.                     stream_Read( p_demux->s, NULL, i_skip );
  347.                 }
  348.                 return VLC_SUCCESS;
  349.             }
  350.             p_peek++;
  351.             i_skip++;
  352.         }
  353.         stream_Read( p_demux->s, NULL, i_skip );
  354.     }
  355.     return VLC_EGENERIC;
  356. }
  357. /*****************************************************************************
  358.  * ReadNSVf:
  359.  *****************************************************************************/
  360. static int ReadNSVf( demux_t *p_demux )
  361. {
  362.     /* demux_sys_t *p_sys = p_demux->p_sys; */
  363.     uint8_t     *p;
  364.     int         i_size;
  365.     msg_Dbg( p_demux, "new NSVf chunk" );
  366.     if( stream_Peek( p_demux->s, &p, 8 ) < 8 )
  367.     {
  368.         return VLC_EGENERIC;
  369.     }
  370.     i_size = GetDWLE( &p[4] );
  371.     msg_Dbg( p_demux, "    - size=%d", i_size );
  372.     return stream_Read( p_demux->s, NULL, i_size ) == i_size ? VLC_SUCCESS : VLC_EGENERIC;
  373. }
  374. /*****************************************************************************
  375.  * ReadNSVf:
  376.  *****************************************************************************/
  377. static int ReadNSVs( demux_t *p_demux )
  378. {
  379.     demux_sys_t *p_sys = p_demux->p_sys;
  380.     uint8_t      header[19];
  381.     vlc_fourcc_t fcc;
  382.     if( stream_Read( p_demux->s, header, 19 ) < 19 )
  383.     {
  384.         msg_Warn( p_demux, "cannot read" );
  385.         return VLC_EGENERIC;
  386.     }
  387.     msg_Dbg( p_demux, "new NSVs chunk" );
  388.     /* Video */
  389.     switch( ( fcc = VLC_FOURCC( header[4], header[5], header[6], header[7] ) ) )
  390.     {
  391.         case VLC_FOURCC( 'V', 'P', '3', ' ' ):
  392.         case VLC_FOURCC( 'V', 'P', '3', '1' ):
  393.             fcc = VLC_FOURCC( 'V', 'P', '3', '1' );
  394.             break;
  395.         case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
  396.             break;
  397.         default:
  398.             msg_Warn( p_demux, "unknown codec" );
  399.             break;
  400.     }
  401.     if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_video.i_codec  )
  402.     {
  403.         es_format_Init( &p_sys->fmt_video, VIDEO_ES, fcc );
  404.         p_sys->fmt_video.video.i_width = GetWLE( &header[12] );
  405.         p_sys->fmt_video.video.i_height = GetWLE( &header[14] );
  406.         if( p_sys->p_video )
  407.         {
  408.             es_out_Del( p_demux->out, p_sys->p_video );
  409.         }
  410.         p_sys->p_video = es_out_Add( p_demux->out, &p_sys->fmt_video );
  411.         msg_Dbg( p_demux, "    - video `%4.4s' %dx%d",
  412.                  (char*)&fcc,
  413.                  p_sys->fmt_video.video.i_width,
  414.                  p_sys->fmt_video.video.i_height );
  415.     }
  416.     /* Audio */
  417.     switch( ( fcc = VLC_FOURCC( header[8], header[9], header[10], header[11] ) ) )
  418.     {
  419.         case VLC_FOURCC( 'M', 'P', '3', ' ' ):
  420.             fcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
  421.             break;
  422.         case VLC_FOURCC( 'P', 'C', 'M', ' ' ):
  423.             fcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
  424.             break;
  425.         case VLC_FOURCC( 'A', 'A', 'C', ' ' ):
  426.             fcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
  427.             break;
  428.         case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
  429.             break;
  430.         default:
  431.             msg_Warn( p_demux, "unknown codec" );
  432.             break;
  433.     }
  434.     if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_audio.i_codec )
  435.     {
  436.         msg_Dbg( p_demux, "    - audio `%4.4s'", (char*)&fcc );
  437.         if( p_sys->p_audio )
  438.         {
  439.             es_out_Del( p_demux->out, p_sys->p_audio );
  440.             p_sys->p_audio = NULL;
  441.         }
  442.         es_format_Init( &p_sys->fmt_audio, AUDIO_ES, fcc );
  443.     }
  444.     if( header[16]&0x80 )
  445.     {
  446.         /* Fractional frame rate */
  447.         switch( header[16]&0x03 )
  448.         {
  449.             case 0: /* 30 fps */
  450.                 p_sys->i_pcr_inc = 33333; /* 300000/9 */
  451.                 break;
  452.             case 1: /* 29.97 fps */
  453.                 p_sys->i_pcr_inc = 33367; /* 300300/9 */
  454.                 break;
  455.             case 2: /* 25 fps */
  456.                 p_sys->i_pcr_inc = 40000; /* 360000/9 */
  457.                 break;
  458.             case 3: /* 23.98 fps */
  459.                 p_sys->i_pcr_inc = 41700; /* 375300/9 */
  460.                 break;
  461.         }
  462.         if( header[16] < 0xc0 )
  463.             p_sys->i_pcr_inc = p_sys->i_pcr_inc * (((header[16] ^ 0x80) >> 2 ) +1 );
  464.         else
  465.             p_sys->i_pcr_inc = p_sys->i_pcr_inc / (((header[16] ^ 0xc0) >> 2 ) +1 );
  466.     }
  467.     else if( header[16] != 0 )
  468.     {
  469.         /* Integer frame rate */
  470.         p_sys->i_pcr_inc = 1000000 / header[16];
  471.     }
  472.     else
  473.     {
  474.         msg_Dbg( p_demux, "invalid fps (0x00)" );
  475.         p_sys->i_pcr_inc = 40000;
  476.     }
  477.     msg_Dbg( p_demux, "    - fps=%.3f", 1000000.0 / (double)p_sys->i_pcr_inc );
  478.     return VLC_SUCCESS;
  479. }