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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * nsv.c: NullSoft Video demuxer.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004-2007 the VideoLAN team
  5.  * $Id: d8cedd1906d947ce7291806f83b5aefb7ecc7e28 $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_demux.h>
  32. /* TODO:
  33.  *  - implement NSVf parsing (to get meta data)
  34.  *  - implement missing Control (and in the right way)
  35.  *  - ...
  36.  */
  37. /*****************************************************************************
  38.  * Module descriptor
  39.  *****************************************************************************/
  40. static int  Open    ( vlc_object_t * );
  41. static void Close  ( vlc_object_t * );
  42. vlc_module_begin ()
  43.     set_description( N_("NullSoft demuxer" ) )
  44.     set_capability( "demux", 10 )
  45.     set_category( CAT_INPUT )
  46.     set_subcategory( SUBCAT_INPUT_DEMUX )
  47.     set_callbacks( Open, Close )
  48.     add_shortcut( "nsv" )
  49. vlc_module_end ()
  50. /*****************************************************************************
  51.  * Local prototypes
  52.  *****************************************************************************/
  53. struct demux_sys_t
  54. {
  55.     es_format_t  fmt_audio;
  56.     es_out_id_t *p_audio;
  57.     es_format_t  fmt_video;
  58.     es_out_id_t *p_video;
  59.     es_format_t  fmt_sub;
  60.     es_out_id_t  *p_sub;
  61.     int64_t     i_pcr;
  62.     int64_t     i_time;
  63.     int64_t     i_pcr_inc;
  64.     bool b_start_record;
  65. };
  66. static int Demux  ( demux_t *p_demux );
  67. static int Control( demux_t *p_demux, int i_query, va_list args );
  68. static int ReSynch( demux_t *p_demux );
  69. static int ReadNSVf( demux_t *p_demux );
  70. static int ReadNSVs( demux_t *p_demux );
  71. /*****************************************************************************
  72.  * Open
  73.  *****************************************************************************/
  74. static int Open( vlc_object_t *p_this )
  75. {
  76.     demux_t     *p_demux = (demux_t*)p_this;
  77.     demux_sys_t *p_sys;
  78.     const uint8_t *p_peek;
  79.     if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
  80.         return VLC_EGENERIC;
  81.     if( memcmp( p_peek, "NSVf", 4 ) && memcmp( p_peek, "NSVs", 4 ) )
  82.     {
  83.        /* In case we had force this demuxer we try to resynch */
  84.         if( !p_demux->b_force || ReSynch( p_demux ) )
  85.             return VLC_EGENERIC;
  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.     p_sys->b_start_record = false;
  101.     return VLC_SUCCESS;
  102. }
  103. /*****************************************************************************
  104.  * Close
  105.  *****************************************************************************/
  106. static void Close( vlc_object_t *p_this )
  107. {
  108.     demux_t     *p_demux = (demux_t*)p_this;
  109.     demux_sys_t *p_sys = p_demux->p_sys;
  110.     free( p_sys );
  111. }
  112. /*****************************************************************************
  113.  * Demux:
  114.  *****************************************************************************/
  115. static int Demux( demux_t *p_demux )
  116. {
  117.     demux_sys_t *p_sys = p_demux->p_sys;
  118.     uint8_t     header[5];
  119.     const uint8_t *p_peek;
  120.     int         i_size;
  121.     block_t     *p_frame;
  122.     for( ;; )
  123.     {
  124.         if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
  125.         {
  126.             msg_Warn( p_demux, "cannot peek" );
  127.             return 0;
  128.         }
  129.         if( !memcmp( p_peek, "NSVf", 4 ) )
  130.         {
  131.             if( ReadNSVf( p_demux ) )
  132.                 return -1;
  133.         }
  134.         else if( !memcmp( p_peek, "NSVs", 4 ) )
  135.         {
  136.             if( p_sys->b_start_record )
  137.             {
  138.                 /* Enable recording once synchronized */
  139.                 stream_Control( p_demux->s, STREAM_SET_RECORD_STATE, true, "nsv" );
  140.                 p_sys->b_start_record = false;
  141.             }
  142.             if( ReadNSVs( p_demux ) )
  143.                 return -1;
  144.             break;
  145.         }
  146.         else if( GetWLE( p_peek ) == 0xbeef )
  147.         {
  148.             /* Next frame of the current NSVs chunk */
  149.             if( stream_Read( p_demux->s, NULL, 2 ) < 2 )
  150.             {
  151.                 msg_Warn( p_demux, "cannot read" );
  152.                 return 0;
  153.             }
  154.             break;
  155.         }
  156.         else
  157.         {
  158.             msg_Err( p_demux, "invalid signature 0x%x (%4.4s)", GetDWLE( p_peek ), (const char*)p_peek );
  159.             if( ReSynch( p_demux ) )
  160.                 return -1;
  161.         }
  162.     }
  163.     if( stream_Read( p_demux->s, header, 5 ) < 5 )
  164.     {
  165.         msg_Warn( p_demux, "cannot read" );
  166.         return 0;
  167.     }
  168.     /* Set PCR */
  169.     es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  170.     /* Read video */
  171.     i_size = ( header[0] >> 4 ) | ( header[1] << 4 ) | ( header[2] << 12 );
  172.     if( i_size > 0 )
  173.     {
  174.         /* extra data ? */
  175.         if( (header[0]&0x0f) != 0x0 )
  176.         {
  177.             uint8_t      aux[6];
  178.             int          i_aux;
  179.             vlc_fourcc_t fcc;
  180.             if( stream_Read( p_demux->s, aux, 6 ) < 6 )
  181.             {
  182.                 msg_Warn( p_demux, "cannot read" );
  183.                 return 0;
  184.             }
  185.             i_aux = GetWLE( aux );
  186.             fcc   = VLC_FOURCC( aux[2], aux[3], aux[4], aux[5] );
  187.             msg_Dbg( p_demux, "Belekas: %d - size=%d fcc=%4.4s",
  188.                      header[0]&0xf, i_aux, (char*)&fcc );
  189.             if( fcc == VLC_FOURCC( 'S', 'U', 'B', 'T' ) && i_aux > 2 )
  190.             {
  191.                 if( p_sys->p_sub == NULL )
  192.                 {
  193.                     p_sys->fmt_sub.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
  194.                     p_sys->p_sub = es_out_Add( p_demux->out, &p_sys->fmt_sub );
  195.                     es_out_Control( p_demux->out, ES_OUT_SET_ES, p_sys->p_sub );
  196.                 }
  197.                 stream_Read( p_demux->s, NULL, 2 );
  198.                 if( ( p_frame = stream_Block( p_demux->s, i_aux - 2 ) ) )
  199.                 {
  200.                     uint8_t *p = p_frame->p_buffer;
  201.                     while( p < &p_frame->p_buffer[p_frame->i_buffer] && *p != 0 )
  202.                     {
  203.                         p++;
  204.                     }
  205.                     if( *p == 0 && p + 1 < &p_frame->p_buffer[p_frame->i_buffer] )
  206.                     {
  207.                         p_frame->i_buffer -= p + 1 - p_frame->p_buffer;
  208.                         p_frame->p_buffer = p + 1;
  209.                     }
  210.                     /* Skip the first part (it is the language name) */
  211.                     p_frame->i_pts = p_sys->i_pcr;
  212.                     p_frame->i_dts = p_sys->i_pcr + 4000000;    /* 4s */
  213.                     es_out_Send( p_demux->out, p_sys->p_sub, p_frame );
  214.                 }
  215.             }
  216.             else
  217.             {
  218.                 /* We skip this extra data */
  219.                 if( stream_Read( p_demux->s, NULL, i_aux ) < i_aux )
  220.                 {
  221.                     msg_Warn( p_demux, "cannot read" );
  222.                     return 0;
  223.                 }
  224.             }
  225.             i_size -= 6 + i_aux;
  226.         }
  227.         /* msg_Dbg( p_demux, "frame video size=%d", i_size ); */
  228.         if( i_size > 0 && ( p_frame = stream_Block( p_demux->s, i_size ) ) )
  229.         {
  230.             p_frame->i_dts = p_sys->i_pcr;
  231.             es_out_Send( p_demux->out, p_sys->p_video, p_frame );
  232.         }
  233.     }
  234.     /* Read audio */
  235.     i_size = header[3] | ( header[4] << 8 );
  236.     if( i_size > 0 )
  237.     {
  238.         /* msg_Dbg( p_demux, "frame audio size=%d", i_size ); */
  239.         if( p_sys->fmt_audio.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
  240.         {
  241.             uint8_t h[4];
  242.             stream_Read( p_demux->s, h, 4 );
  243.             p_sys->fmt_audio.audio.i_channels = h[1];
  244.             p_sys->fmt_audio.audio.i_rate = GetWLE( &h[2] );
  245.             i_size -= 4;
  246.         }
  247.         if( p_sys->p_audio == NULL )
  248.         {
  249.             p_sys->p_audio = es_out_Add( p_demux->out, &p_sys->fmt_audio );
  250.         }
  251.         if( ( p_frame = stream_Block( p_demux->s, i_size ) ) )
  252.         {
  253.             p_frame->i_dts =
  254.             p_frame->i_pts = p_sys->i_pcr;
  255.             es_out_Send( p_demux->out, p_sys->p_audio, p_frame );
  256.         }
  257.     }
  258.     p_sys->i_pcr += p_sys->i_pcr_inc;
  259.     if( p_sys->i_time >= 0 )
  260.     {
  261.         p_sys->i_time += p_sys->i_pcr_inc;
  262.     }
  263.     return 1;
  264. }
  265. /*****************************************************************************
  266.  * Control:
  267.  *****************************************************************************/
  268. static int Control( demux_t *p_demux, int i_query, va_list args )
  269. {
  270.     demux_sys_t *p_sys = p_demux->p_sys;
  271.     double f, *pf;
  272.     bool b_bool, *pb_bool;
  273.     int64_t i64, *pi64;
  274.     switch( i_query )
  275.     {
  276.         case DEMUX_GET_POSITION:
  277.             pf = (double*) va_arg( args, double* );
  278.             i64 = stream_Size( p_demux->s );
  279.             if( i64 > 0 )
  280.             {
  281.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  282.             }
  283.             else
  284.             {
  285.                 *pf = 0.0;
  286.             }
  287.             return VLC_SUCCESS;
  288.         case DEMUX_SET_POSITION:
  289.             f = (double) va_arg( args, double );
  290.             i64 = stream_Size( p_demux->s );
  291.             if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) || ReSynch( p_demux ) )
  292.                 return VLC_EGENERIC;
  293.             p_sys->i_time = -1; /* Invalidate time display */
  294.             return VLC_SUCCESS;
  295.         case DEMUX_GET_TIME:
  296.             pi64 = (int64_t*)va_arg( args, int64_t * );
  297.             if( p_sys->i_time < 0 )
  298.             {
  299.                 *pi64 = 0;
  300.                 return VLC_EGENERIC;
  301.             }
  302.             *pi64 = p_sys->i_time;
  303.             return VLC_SUCCESS;
  304. #if 0
  305.         case DEMUX_GET_LENGTH:
  306.             pi64 = (int64_t*)va_arg( args, int64_t * );
  307.             if( p_sys->i_mux_rate > 0 )
  308.             {
  309.                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
  310.                 return VLC_SUCCESS;
  311.             }
  312.             *pi64 = 0;
  313.             return VLC_EGENERIC;
  314. #endif
  315.         case DEMUX_GET_FPS:
  316.             pf = (double*)va_arg( args, double * );
  317.             *pf = (double)1000000.0 / (double)p_sys->i_pcr_inc;
  318.             return VLC_SUCCESS;
  319.         case DEMUX_CAN_RECORD:
  320.             pb_bool = (bool*)va_arg( args, bool * );
  321.             *pb_bool = true;
  322.             return VLC_SUCCESS;
  323.         case DEMUX_SET_RECORD_STATE:
  324.             b_bool = (bool)va_arg( args, int );
  325.             if( !b_bool )
  326.                 stream_Control( p_demux->s, STREAM_SET_RECORD_STATE, false );
  327.             p_sys->b_start_record = b_bool;
  328.             return VLC_SUCCESS;
  329.         case DEMUX_SET_TIME:
  330.         default:
  331.             return VLC_EGENERIC;
  332.     }
  333. }
  334. /*****************************************************************************
  335.  * ReSynch:
  336.  *****************************************************************************/
  337. static int ReSynch( demux_t *p_demux )
  338. {
  339.     const uint8_t *p_peek;
  340.     int      i_skip;
  341.     int      i_peek;
  342.     while( vlc_object_alive (p_demux) )
  343.     {
  344.         if( ( i_peek = stream_Peek( p_demux->s, &p_peek, 1024 ) ) < 8 )
  345.         {
  346.             return VLC_EGENERIC;
  347.         }
  348.         i_skip = 0;
  349.         while( i_skip < i_peek - 4 )
  350.         {
  351.             if( !memcmp( p_peek, "NSVf", 4 )
  352.              || !memcmp( p_peek, "NSVs", 4 ) )
  353.             {
  354.                 if( i_skip > 0 )
  355.                 {
  356.                     stream_Read( p_demux->s, NULL, i_skip );
  357.                 }
  358.                 return VLC_SUCCESS;
  359.             }
  360.             p_peek++;
  361.             i_skip++;
  362.         }
  363.         stream_Read( p_demux->s, NULL, i_skip );
  364.     }
  365.     return VLC_EGENERIC;
  366. }
  367. /*****************************************************************************
  368.  * ReadNSVf:
  369.  *****************************************************************************/
  370. static int ReadNSVf( demux_t *p_demux )
  371. {
  372.     /* demux_sys_t *p_sys = p_demux->p_sys; */
  373.     const uint8_t     *p;
  374.     int         i_size;
  375.     msg_Dbg( p_demux, "new NSVf chunk" );
  376.     if( stream_Peek( p_demux->s, &p, 8 ) < 8 )
  377.     {
  378.         return VLC_EGENERIC;
  379.     }
  380.     i_size = GetDWLE( &p[4] );
  381.     msg_Dbg( p_demux, "    - size=%d", i_size );
  382.     return stream_Read( p_demux->s, NULL, i_size ) == i_size ? VLC_SUCCESS : VLC_EGENERIC;
  383. }
  384. /*****************************************************************************
  385.  * ReadNSVf:
  386.  *****************************************************************************/
  387. static int ReadNSVs( demux_t *p_demux )
  388. {
  389.     demux_sys_t *p_sys = p_demux->p_sys;
  390.     uint8_t      header[19];
  391.     vlc_fourcc_t fcc;
  392.     if( stream_Read( p_demux->s, header, 19 ) < 19 )
  393.     {
  394.         msg_Warn( p_demux, "cannot read" );
  395.         return VLC_EGENERIC;
  396.     }
  397.     /* Video */
  398.     switch( ( fcc = VLC_FOURCC( header[4], header[5], header[6], header[7] ) ) )
  399.     {
  400.         case VLC_FOURCC( 'V', 'P', '3', ' ' ):
  401.         case VLC_FOURCC( 'V', 'P', '3', '0' ):
  402.             fcc = VLC_FOURCC( 'V', 'P', '3', '0' );
  403.             break;
  404.         case VLC_FOURCC( 'V', 'P', '3', '1' ):
  405.             fcc = VLC_FOURCC( 'V', 'P', '3', '1' );
  406.             break;
  407.         case VLC_FOURCC( 'V', 'P', '5', ' ' ):
  408.         case VLC_FOURCC( 'V', 'P', '5', '0' ):
  409.             fcc = VLC_FOURCC( 'V', 'P', '5', '0' );
  410.             break;
  411.         case VLC_FOURCC( 'V', 'P', '6', '0' ):
  412.         case VLC_FOURCC( 'V', 'P', '6', '1' ):
  413.         case VLC_FOURCC( 'V', 'P', '6', '2' ):
  414.         case VLC_FOURCC( 'H', '2', '6', '4' ):
  415.         case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
  416.             break;
  417.         default:
  418.             msg_Warn( p_demux, "unknown codec %4.4s", (char *)&fcc );
  419.             break;
  420.     }
  421.     if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_video.i_codec  )
  422.     {
  423.         es_format_Init( &p_sys->fmt_video, VIDEO_ES, fcc );
  424.         p_sys->fmt_video.video.i_width = GetWLE( &header[12] );
  425.         p_sys->fmt_video.video.i_height = GetWLE( &header[14] );
  426.         if( p_sys->p_video )
  427.         {
  428.             es_out_Del( p_demux->out, p_sys->p_video );
  429.         }
  430.         p_sys->p_video = es_out_Add( p_demux->out, &p_sys->fmt_video );
  431.         msg_Dbg( p_demux, "    - video `%4.4s' %dx%d",
  432.                  (char*)&fcc,
  433.                  p_sys->fmt_video.video.i_width,
  434.                  p_sys->fmt_video.video.i_height );
  435.     }
  436.     /* Audio */
  437.     switch( ( fcc = VLC_FOURCC( header[8], header[9], header[10], header[11] ) ) )
  438.     {
  439.         case VLC_FOURCC( 'M', 'P', '3', ' ' ):
  440.             fcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
  441.             break;
  442.         case VLC_FOURCC( 'P', 'C', 'M', ' ' ):
  443.             fcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
  444.             break;
  445.         case VLC_FOURCC( 'A', 'A', 'C', ' ' ):
  446.         case VLC_FOURCC( 'A', 'A', 'C', 'P' ):
  447.             fcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
  448.             break;
  449.         case VLC_FOURCC( 'S', 'P', 'X', ' ' ):
  450.             fcc = VLC_FOURCC( 's', 'p', 'x', ' ' );
  451.             break;
  452.         case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
  453.             break;
  454.         default:
  455.             msg_Warn( p_demux, "unknown codec %4.4s", (char *)&fcc );
  456.             break;
  457.     }
  458.     if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_audio.i_codec )
  459.     {
  460.         msg_Dbg( p_demux, "    - audio `%4.4s'", (char*)&fcc );
  461.         if( p_sys->p_audio )
  462.         {
  463.             es_out_Del( p_demux->out, p_sys->p_audio );
  464.             p_sys->p_audio = NULL;
  465.         }
  466.         es_format_Init( &p_sys->fmt_audio, AUDIO_ES, fcc );
  467.     }
  468.     if( header[16]&0x80 )
  469.     {
  470.         /* Fractional frame rate */
  471.         switch( header[16]&0x03 )
  472.         {
  473.             case 0: /* 30 fps */
  474.                 p_sys->i_pcr_inc = 33333; /* 300000/9 */
  475.                 break;
  476.             case 1: /* 29.97 fps */
  477.                 p_sys->i_pcr_inc = 33367; /* 300300/9 */
  478.                 break;
  479.             case 2: /* 25 fps */
  480.                 p_sys->i_pcr_inc = 40000; /* 360000/9 */
  481.                 break;
  482.             case 3: /* 23.98 fps */
  483.                 p_sys->i_pcr_inc = 41700; /* 375300/9 */
  484.                 break;
  485.         }
  486.         if( header[16] < 0xc0 )
  487.             p_sys->i_pcr_inc = p_sys->i_pcr_inc * (((header[16] ^ 0x80) >> 2 ) +1 );
  488.         else
  489.             p_sys->i_pcr_inc = p_sys->i_pcr_inc / (((header[16] ^ 0xc0) >> 2 ) +1 );
  490.     }
  491.     else if( header[16] != 0 )
  492.     {
  493.         /* Integer frame rate */
  494.         p_sys->i_pcr_inc = 1000000 / header[16];
  495.     }
  496.     else
  497.     {
  498.         msg_Dbg( p_demux, "invalid fps (0x00)" );
  499.         p_sys->i_pcr_inc = 40000;
  500.     }
  501.     //msg_Dbg( p_demux, "    - fps=%.3f", 1000000.0 / (double)p_sys->i_pcr_inc );
  502.     return VLC_SUCCESS;
  503. }