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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * real.c: Real demuxer.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: real.c 9014 2004-10-18 23:05:30Z hartman $
  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. /*****************************************************************************
  30.  * Module descriptor
  31.  *****************************************************************************/
  32. static int  Open    ( vlc_object_t * );
  33. static void Close  ( vlc_object_t * );
  34. vlc_module_begin();
  35.     set_description( _("Real demuxer" ) );
  36.     set_capability( "demux2", 15 );
  37.     set_callbacks( Open, Close );
  38.     add_shortcut( "real" );
  39.     add_shortcut( "rm" );
  40. vlc_module_end();
  41. /*****************************************************************************
  42.  * Local prototypes
  43.  *****************************************************************************/
  44. typedef struct
  45. {
  46.     int         i_id;
  47.     es_format_t fmt;
  48.     es_out_id_t *p_es;
  49.     int         i_frame;
  50.     block_t     *p_frame;
  51. } real_track_t;
  52. struct demux_sys_t
  53. {
  54.     int64_t  i_data_offset;
  55.     int64_t  i_data_size;
  56.     uint32_t i_data_packets_count;
  57.     uint32_t i_data_packets;
  58.     int64_t  i_data_offset_next;
  59.     int          i_track;
  60.     real_track_t **track;
  61.     uint8_t buffer[65536];
  62.     int64_t     i_pcr;
  63. };
  64. static int Demux( demux_t *p_demux );
  65. static int Control( demux_t *p_demux, int i_query, va_list args );
  66. static int HeaderRead( demux_t *p_demux );
  67. /*****************************************************************************
  68.  * Open
  69.  *****************************************************************************/
  70. static int Open( vlc_object_t *p_this )
  71. {
  72.     demux_t     *p_demux = (demux_t*)p_this;
  73.     demux_sys_t *p_sys;
  74.     uint8_t     *p_peek;
  75.     if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 )
  76.     {
  77.         msg_Err( p_demux, "cannot peek" );
  78.         return VLC_EGENERIC;
  79.     }
  80.     if( strncmp( p_peek, ".RMF", 4 ) )
  81.     {
  82.         msg_Warn( p_demux, "Real module discarded" );
  83.         return VLC_EGENERIC;
  84.     }
  85.     /* Fill p_demux field */
  86.     p_demux->pf_demux = Demux;
  87.     p_demux->pf_control = Control;
  88.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  89.     p_sys->i_data_offset = 0;
  90.     p_sys->i_track = 0;
  91.     p_sys->track   = NULL;
  92.     p_sys->i_pcr   = 1;
  93.     /* Parse the headers */
  94.     if( HeaderRead( p_demux ) )
  95.     {
  96.         int i;
  97.         msg_Err( p_demux, "invalid header" );
  98.         for( i = 0; i < p_sys->i_track; i++ )
  99.         {
  100.             real_track_t *tk = p_sys->track[i];
  101.             if( tk->p_es )
  102.             {
  103.                 es_out_Del( p_demux->out, tk->p_es );
  104.             }
  105.             free( tk );
  106.         }
  107.         if( p_sys->i_track > 0 )
  108.         {
  109.             free( p_sys->track );
  110.         }
  111.         free( p_sys );
  112.         return VLC_EGENERIC;
  113.     }
  114.     return VLC_SUCCESS;
  115. }
  116. /*****************************************************************************
  117.  * Close
  118.  *****************************************************************************/
  119. static void Close( vlc_object_t *p_this )
  120. {
  121.     demux_t *p_demux = (demux_t*)p_this;
  122.     demux_sys_t *p_sys = p_demux->p_sys;
  123.     int i;
  124.     for( i = 0; i < p_sys->i_track; i++ )
  125.     {
  126.         real_track_t *tk = p_sys->track[i];
  127.         if( tk->p_frame )
  128.         {
  129.             block_Release( tk->p_frame );
  130.         }
  131.         free( tk );
  132.     }
  133.     if( p_sys->i_track > 0 )
  134.     {
  135.         free( p_sys->track );
  136.     }
  137.     free( p_sys );
  138. }
  139. /*****************************************************************************
  140.  * Demux:
  141.  *****************************************************************************/
  142. static int Demux( demux_t *p_demux )
  143. {
  144.     demux_sys_t *p_sys = p_demux->p_sys;
  145.     uint8_t     header[18];
  146.     int         i_size;
  147.     int         i_id;
  148.     int64_t     i_pts;
  149.     int         i;
  150.     real_track_t *tk = NULL;
  151.     vlc_bool_t  b_selected;
  152.     if( p_sys->i_data_packets >= p_sys->i_data_packets_count )
  153.     {
  154.         if( stream_Read( p_demux->s, header, 18 ) < 18 )
  155.         {
  156.             return 0;
  157.         }
  158.         if( strncmp( header, "DATA", 4 ) )
  159.         {
  160.             return 0;
  161.         }
  162.         p_sys->i_data_offset = stream_Tell( p_demux->s ) - 18;
  163.         p_sys->i_data_size   = GetDWBE( &header[4] );
  164.         p_sys->i_data_packets_count = GetDWBE( &header[10] );
  165.         p_sys->i_data_packets = 0;
  166.         p_sys->i_data_offset_next = GetDWBE( &header[14] );
  167.         msg_Dbg( p_demux, "entering new DATA packets=%d next=%u",
  168.                  p_sys->i_data_packets_count,
  169.                  (uint32_t)p_sys->i_data_offset_next );
  170.     }
  171.     if( stream_Read( p_demux->s, header, 12 ) < 12 )
  172.     {
  173.         return 0;
  174.     }
  175.     i_size = GetWBE( &header[2] ) - 12;
  176.     i_id   = GetWBE( &header[4] );
  177.     i_pts  = 1000 * GetDWBE( &header[6] );
  178.     /* header[11] -> flags 0x02 -> keyframe */
  179.     msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u",
  180.              p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) );
  181.     p_sys->i_data_packets++;
  182.     stream_Read( p_demux->s, p_sys->buffer, i_size );
  183.     for( i = 0; i < p_sys->i_track; i++ )
  184.     {
  185.         if( p_sys->track[i]->i_id == i_id )
  186.         {
  187.             tk = p_sys->track[i];
  188.         }
  189.     }
  190.     if( tk == NULL )
  191.     {
  192.         msg_Warn( p_demux, "unknown track id(0x%x)", i_id );
  193.         return 1;
  194.     }
  195.     es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b_selected );
  196.     if( tk->fmt.i_cat == VIDEO_ES && b_selected )
  197.     {
  198.         uint8_t     *p = p_sys->buffer;
  199.         while( p < &p_sys->buffer[i_size - 2] )
  200.         {
  201.             uint8_t h = *p++;
  202.             int     i_len = 0;
  203.             int     i_copy;
  204.             int     i_subseq = 0;
  205.             int     i_seqnum = 0;
  206.             int     i_offset = 0;
  207.             if( (h&0xc0) == 0x40 )
  208.             {
  209.                 /* Short header */
  210.                 p++;
  211.                 i_len = &p_sys->buffer[i_size] - p;
  212.             }
  213.             else
  214.             {
  215.                 if( (h&0x40) == 0 )
  216.                 {
  217.                     i_subseq = (*p++)&0x7f;
  218.                 }
  219.                 i_len = (p[0] << 8)|p[1]; p += 2;
  220.                 if( (i_len&0xc000) == 0 )
  221.                 {
  222.                     i_len <<= 16;
  223.                     i_len |= (p[0] << 8)|p[1]; p += 2;
  224.                     i_len &= 0x3fffffff;
  225.                 }
  226.                 else
  227.                 {
  228.                     i_len &= 0x3fff;
  229.                 }
  230.                 i_offset = (p[0] << 8)|p[1]; p += 2;
  231.                 if( (i_offset&0xc000) == 0 )
  232.                 {
  233.                     i_offset <<= 16;
  234.                     i_offset |= (p[0] << 8)|p[1]; p += 2;
  235.                     i_offset &= 0x3fffffff;
  236.                 }
  237.                 else
  238.                 {
  239.                     i_offset &= 0x3fff;
  240.                 }
  241.                 i_seqnum = *p++;
  242.             }
  243.             i_copy = i_len - i_offset;
  244.             if( i_copy > &p_sys->buffer[i_size] - p )
  245.             {
  246.                 i_copy = &p_sys->buffer[i_size] - p;
  247.             }
  248.             else if( i_copy < 0 )
  249.             {
  250.                 break;
  251.             }
  252.             msg_Dbg( p_demux, "    - len=%d offset=%d size=%d subseq=%d seqnum=%d",
  253.                      i_len, i_offset, i_copy, i_subseq, i_seqnum );
  254.             if( (h&0xc0) == 0x80 )
  255.             {
  256.                 /* last fragment -> fixes */
  257.                 i_copy = i_offset;
  258.                 i_offset = i_len - i_copy;
  259.                 msg_Dbg( p_demux, "last fixing copy=%d offset=%d", i_copy, i_offset );
  260.             }
  261.             if( tk->p_frame &&
  262.                 ( tk->p_frame->i_dts != i_pts ||
  263.                   tk->i_frame != i_len ) )
  264.             {
  265.                 msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer );
  266.                 if( p_sys->i_pcr < tk->p_frame->i_dts )
  267.                 {
  268.                     p_sys->i_pcr = tk->p_frame->i_dts;
  269.                     es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  270.                 }
  271.                 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
  272.                 tk->i_frame = 0;
  273.                 tk->p_frame = NULL;
  274.             }
  275.             if( (h&0xc0) != 0x80 && (h&0xc0) != 0x00 && tk->p_frame == NULL )
  276.             {
  277.                 /* no fragment */
  278.                 i_len = i_copy;
  279.                 i_offset = 0;
  280.             }
  281.             if( tk->p_frame == NULL )
  282.             {
  283.                 msg_Dbg( p_demux, "new frame size=%d", i_len );
  284.                 tk->i_frame = i_len;
  285.                 if( ( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) == NULL )
  286.                 {
  287.                     return -1;
  288.                 }
  289.                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
  290.                 tk->p_frame->i_dts = i_pts;
  291.                 tk->p_frame->i_pts = i_pts;
  292.                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
  293.                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 0;      /* chunk counts */
  294.             }
  295.             if( i_offset < tk->i_frame)
  296.             {
  297.                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
  298.                 msg_Dbg( p_demux, "copying new buffer n=%d offset=%d copy=%d", i_ck, i_offset, i_copy );
  299.                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
  300.                 memcpy( &tk->p_frame->p_buffer[i_offset + 8],
  301.                         p, i_copy );
  302.             }
  303.             p += i_copy;
  304.             if( (h&0xc0) != 0x80 )
  305.             {
  306.                 break;
  307.             }
  308. #if 0
  309.             if( tk->p_frame )
  310.             {
  311.                 /* append data */
  312.                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
  313.                 if( (h&0xc0) == 0x80 )
  314.                 {
  315.                     /* last fragment */
  316.                     i_copy = i_offset;
  317.                     i_offset = i_len - i_offset;
  318.                     ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
  319.                     memcpy( &tk->p_frame->p_buffer[i_offset+ 8], p, i_copy );
  320.                     p += i_copy;
  321.                     if( p_sys->i_pcr < tk->p_frame->i_dts )
  322.                     {
  323.                         p_sys->i_pcr = tk->p_frame->i_dts;
  324.                         es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  325.                     }
  326.                     es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
  327.                     tk->i_frame = 0;
  328.                     tk->p_frame = NULL;
  329.                     continue;
  330.                 }
  331.                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
  332.                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
  333.                 break;
  334.             }
  335.             if( (h&0xc0) != 0x00 )
  336.             {
  337.                 block_t *p_frame;
  338.                 /* not fragmented */
  339.                 if( ( p_frame = block_New( p_demux, i_copy + 8 + 8 ) ) == NULL )
  340.                 {
  341.                     return -1;
  342.                 }
  343.                 p_frame->i_dts = i_pts;
  344.                 p_frame->i_pts = i_pts;
  345.                 ((uint32_t*)p_frame->p_buffer)[0] = i_copy;
  346.                 ((uint32_t*)p_frame->p_buffer)[1] = 1;
  347.                 ((uint32_t*)(p_frame->p_buffer+i_copy+8))[0] = 0;
  348.                 memcpy( &p_frame->p_buffer[8], p, i_copy );
  349.                 p += i_copy;
  350.                 if( p_sys->i_pcr < p_frame->i_dts )
  351.                 {
  352.                     p_sys->i_pcr = p_frame->i_dts;
  353.                     es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  354.                 }
  355.                 es_out_Send( p_demux->out, tk->p_es, p_frame );
  356.             }
  357.             else
  358.             {
  359.                 /* First fragment */
  360.                 tk->i_frame = i_len;
  361.                 if( ( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) == NULL )
  362.                 {
  363.                     return -1;
  364.                 }
  365.                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
  366.                 tk->p_frame->i_dts = i_pts;
  367.                 tk->p_frame->i_pts = i_pts;
  368.                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
  369.                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 1;      /* chunk counts */
  370.                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[0] = i_offset;
  371.                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
  372.                 break;
  373.             }
  374. #endif
  375.         }
  376.     }
  377.     else if( tk->fmt.i_cat == AUDIO_ES && b_selected )
  378.     {
  379.         /* Set PCR */
  380.         if( p_sys->i_pcr < i_pts )
  381.         {
  382.             p_sys->i_pcr = i_pts;
  383.             es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
  384.         }
  385.         if( tk->fmt.i_codec == VLC_FOURCC( 'm', 'p', '4', 'a' ) )
  386.         {
  387.             int     i_sub = (p_sys->buffer[1] >> 4)&0x0f;
  388.             uint8_t *p_sub = &p_sys->buffer[2+2*i_sub];
  389.             int i;
  390.             for( i = 0; i < i_sub; i++ )
  391.             {
  392.                 int i_sub_size = GetWBE( &p_sys->buffer[2+i*2]);
  393.                 block_t *p_block = block_New( p_demux, i_sub_size );
  394.                 if( p_block )
  395.                 {
  396.                     memcpy( p_block->p_buffer, p_sub, i_sub_size );
  397.                     p_sub += i_sub_size;
  398.                     p_block->i_dts =
  399.                     p_block->i_pts = ( i == 0 ? i_pts : 0 );
  400.                     es_out_Send( p_demux->out, tk->p_es, p_block );
  401.                 }
  402.             }
  403.         }
  404.         else
  405.         {
  406.             block_t *p_block = block_New( p_demux, i_size );
  407.             if( tk->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', ' ' ) )
  408.             {
  409.                 uint8_t *src = p_sys->buffer;
  410.                 uint8_t *dst = p_block->p_buffer;
  411.                 /* byte swap data */
  412.                 while( dst < &p_block->p_buffer[i_size- 1])
  413.                 {
  414.                     *dst++ = src[1];
  415.                     *dst++ = src[0];
  416.                     src += 2;
  417.                 }
  418.             }
  419.             else
  420.             {
  421.                 memcpy( p_block->p_buffer, p_sys->buffer, i_size );
  422.             }
  423.             p_block->i_dts =
  424.             p_block->i_pts = i_pts;
  425.             es_out_Send( p_demux->out, tk->p_es, p_block );
  426.         }
  427.     }
  428.     return 1;
  429. }
  430. /*****************************************************************************
  431.  * Control:
  432.  *****************************************************************************/
  433. static int Control( demux_t *p_demux, int i_query, va_list args )
  434. {
  435. #if 0
  436.     demux_sys_t *p_sys = p_demux->p_sys;
  437.     double f, *pf;
  438.     int64_t i64, *pi64;
  439.     switch( i_query )
  440.     {
  441.         case DEMUX_GET_POSITION:
  442.             pf = (double*) va_arg( args, double* );
  443.             i64 = stream_Size( p_demux->s );
  444.             if( i64 > 0 )
  445.             {
  446.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  447.             }
  448.             else
  449.             {
  450.                 *pf = 0.0;
  451.             }
  452.             return VLC_SUCCESS;
  453.         case DEMUX_SET_POSITION:
  454.             f = (double) va_arg( args, double );
  455.             i64 = stream_Size( p_demux->s );
  456.             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  457.             return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
  458.         case DEMUX_GET_TIME:
  459.             pi64 = (int64_t*)va_arg( args, int64_t * );
  460.             if( p_sys->i_mux_rate > 0 )
  461.             {
  462.                 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
  463.                 return VLC_SUCCESS;
  464.             }
  465.             *pi64 = 0;
  466.             return VLC_EGENERIC;
  467.         case DEMUX_GET_LENGTH:
  468.             pi64 = (int64_t*)va_arg( args, int64_t * );
  469.             if( p_sys->i_mux_rate > 0 )
  470.             {
  471.                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
  472.                 return VLC_SUCCESS;
  473.             }
  474.             *pi64 = 0;
  475.             return VLC_EGENERIC;
  476.         case DEMUX_SET_TIME:
  477.         case DEMUX_GET_FPS:
  478.         default:
  479.             return VLC_EGENERIC;
  480.     }
  481. #endif
  482.     return VLC_EGENERIC;
  483. }
  484. /*****************************************************************************
  485.  * HeaderRead:
  486.  *****************************************************************************/
  487. static int HeaderRead( demux_t *p_demux )
  488. {
  489.     demux_sys_t *p_sys = p_demux->p_sys;
  490.     uint8_t header[100];    /* FIXME */
  491.     uint32_t    i_id;
  492.     uint32_t    i_size;
  493.     int64_t     i_skip;
  494.     int         i_version;
  495.     for( ;; )
  496.     {
  497.         /* Read the header */
  498.         if( stream_Read( p_demux->s, header, 10 ) < 10 )
  499.         {
  500.             return VLC_EGENERIC;
  501.         }
  502.         i_id        = VLC_FOURCC( header[0], header[1], header[2], header[3] );
  503.         i_size      = GetDWBE( &header[4] );
  504.         i_version   = GetWBE( &header[8] );
  505.         msg_Dbg( p_demux, "object %4.4s size=%d version=%d",
  506.                  (char*)&i_id, i_size, i_version );
  507.         if( i_size < 10 )
  508.         {
  509.             return VLC_EGENERIC;
  510.         }
  511.         i_skip = i_size - 10;
  512.         if( i_id == VLC_FOURCC('.','R','M','F') )
  513.         {
  514.             if( stream_Read( p_demux->s, header, 8 ) < 8 )
  515.             {
  516.                 return VLC_EGENERIC;
  517.             }
  518.             msg_Dbg( p_demux, "    - file version=0x%x num headers=%d",
  519.                      GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
  520.             i_skip -= 8;
  521.         }
  522.         else if( i_id == VLC_FOURCC('P','R','O','P') )
  523.         {
  524.             int i_flags;
  525.             if( stream_Read( p_demux->s, header, 40 ) < 40 )
  526.             {
  527.                 return VLC_EGENERIC;
  528.             }
  529.             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d",
  530.                      GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
  531.             msg_Dbg( p_demux, "    - max packet size=%d avg bitrate=%d",
  532.                      GetDWBE( &header[8] ), GetDWBE( &header[12] ) );
  533.             msg_Dbg( p_demux, "    - packets count=%d", GetDWBE( &header[16] ) );
  534.             msg_Dbg( p_demux, "    - duration=%d ms", GetDWBE( &header[20] ) );
  535.             msg_Dbg( p_demux, "    - preroll=%d ms", GetDWBE( &header[24] ) );
  536.             msg_Dbg( p_demux, "    - index offset=%d", GetDWBE( &header[28] ) );
  537.             msg_Dbg( p_demux, "    - data offset=%d", GetDWBE( &header[32] ) );
  538.             msg_Dbg( p_demux, "    - num streams=%d", GetWBE( &header[36] ) );
  539.             i_flags = GetWBE( &header[38]);
  540.             msg_Dbg( p_demux, "    - flags=0x%x %s%s%s",
  541.                      i_flags,
  542.                      i_flags&0x0001 ? "PN_SAVE_ENABLED " : "",
  543.                      i_flags&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
  544.                      i_flags&0x0004 ? "PN_LIVE_BROADCAST" : "" );
  545.             i_skip -= 40;
  546.         }
  547.         else if( i_id == VLC_FOURCC('C','O','N','T') )
  548.         {
  549.             int i_len;
  550.             char *psz;
  551.             stream_Read( p_demux->s, header, 2 );
  552.             if( ( i_len = GetWBE( header ) ) > 0 )
  553.             {
  554.                 psz = malloc( i_len + 1 );
  555.                 stream_Read( p_demux->s, psz, i_len );
  556.                 psz[i_len] = '';
  557.                 msg_Dbg( p_demux, "    - title=`%s'", psz );
  558.                 free( psz );
  559.                 i_skip -= i_len;
  560.             }
  561.             i_skip -= 2;
  562.             stream_Read( p_demux->s, header, 2 );
  563.             if( ( i_len = GetWBE( header ) ) > 0 )
  564.             {
  565.                 psz = malloc( i_len + 1 );
  566.                 stream_Read( p_demux->s, psz, i_len );
  567.                 psz[i_len] = '';
  568.                 msg_Dbg( p_demux, "    - author=`%s'", psz );
  569.                 free( psz );
  570.                 i_skip -= i_len;
  571.             }
  572.             i_skip -= 2;
  573.             stream_Read( p_demux->s, header, 2 );
  574.             if( ( i_len = GetWBE( header ) ) > 0 )
  575.             {
  576.                 psz = malloc( i_len + 1 );
  577.                 stream_Read( p_demux->s, psz, i_len );
  578.                 psz[i_len] = '';
  579.                 msg_Dbg( p_demux, "    - copyright=`%s'", psz );
  580.                 free( psz );
  581.                 i_skip -= i_len;
  582.             }
  583.             i_skip -= 2;
  584.             stream_Read( p_demux->s, header, 2 );
  585.             if( ( i_len = GetWBE( header ) ) > 0 )
  586.             {
  587.                 psz = malloc( i_len + 1 );
  588.                 stream_Read( p_demux->s, psz, i_len );
  589.                 psz[i_len] = '';
  590.                 msg_Dbg( p_demux, "    - comment=`%s'", psz );
  591.                 free( psz );
  592.                 i_skip -= i_len;
  593.             }
  594.             i_skip -= 2;
  595.         }
  596.         else if( i_id == VLC_FOURCC('M','D','P','R') )
  597.         {
  598.             int  i_num;
  599.             int  i_len;
  600.             char *psz;
  601.             if( stream_Read( p_demux->s, header, 30 ) < 30 )
  602.             {
  603.                 return VLC_EGENERIC;
  604.             }
  605.             i_num = GetWBE( header );
  606.             msg_Dbg( p_demux, "    - id=0x%x", i_num );
  607.             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d", GetDWBE( &header[2] ), GetDWBE( &header[6] ) );
  608.             msg_Dbg( p_demux, "    - max packet size=%d avg packet size=%d", GetDWBE( &header[10] ), GetDWBE( &header[14] ));
  609.             msg_Dbg( p_demux, "    - start time=%d", GetDWBE( &header[18] ) );
  610.             msg_Dbg( p_demux, "    - preroll=%d", GetDWBE( &header[22] ) );
  611.             msg_Dbg( p_demux, "    - duration=%d", GetDWBE( &header[26] ));
  612.             i_skip -= 30;
  613.             stream_Read( p_demux->s, header, 1 );
  614.             if( ( i_len = header[0] ) > 0 )
  615.             {
  616.                 psz = malloc( i_len + 1 );
  617.                 stream_Read( p_demux->s, psz, i_len );
  618.                 psz[i_len] = '';
  619.                 msg_Dbg( p_demux, "    - name=`%s'", psz );
  620.                 free( psz );
  621.                 i_skip -= i_len;
  622.             }
  623.             i_skip--;
  624.             stream_Read( p_demux->s, header, 1 );
  625.             if( ( i_len = header[0] ) > 0 )
  626.             {
  627.                 psz = malloc( i_len + 1 );
  628.                 stream_Read( p_demux->s, psz, i_len );
  629.                 psz[i_len] = '';
  630.                 msg_Dbg( p_demux, "    - mime=`%s'", psz );
  631.                 free( psz );
  632.                 i_skip -= i_len;
  633.             }
  634.             i_skip--;
  635.             stream_Read( p_demux->s, header, 4 );
  636.             if( ( i_len = GetDWBE( header ) ) > 0 )
  637.             {
  638.                 es_format_t  fmt;
  639.                 real_track_t *tk;
  640.                 uint8_t *p_peek;
  641.                 msg_Dbg( p_demux, "    - specific data len=%d", i_len );
  642.                 if( stream_Peek( p_demux->s, &p_peek, 34 ) >= 34 )
  643.                 {
  644.                     if( !strncmp( &p_peek[4], "VIDO", 4 ) )
  645.                     {
  646.                         es_format_Init( &fmt, VIDEO_ES,
  647.                                         VLC_FOURCC( p_peek[8], p_peek[9], p_peek[10], p_peek[11] ) );
  648.                         fmt.video.i_width = GetWBE( &p_peek[12] );
  649.                         fmt.video.i_height= GetWBE( &p_peek[14] );
  650.                         fmt.i_extra = 8;
  651.                         fmt.p_extra = malloc( 8 );
  652.                         ((uint32_t*)fmt.p_extra)[0] = GetDWBE( &p_peek[26] );
  653.                         ((uint32_t*)fmt.p_extra)[1] = GetDWBE( &p_peek[30] );
  654.                         msg_Dbg( p_demux, "    - video 0x%08x 0x%08x",
  655.                                  ((uint32_t*)fmt.p_extra)[0],
  656.                                  ((uint32_t*)fmt.p_extra)[1] );
  657.                         if( GetDWBE( &p_peek[30] ) == 0x10003000 ||
  658.                             GetDWBE( &p_peek[30] ) == 0x10003001 )
  659.                         {
  660.                             fmt.i_codec = VLC_FOURCC( 'R','V','1','3' );
  661.                         }
  662.                         msg_Dbg( p_demux, "    - video %4.4s %dx%d",
  663.                                  (char*)&fmt.i_codec,
  664.                                  fmt.video.i_width, fmt.video.i_height );
  665.                         tk = malloc( sizeof( real_track_t ) );
  666.                         tk->i_id = i_num;
  667.                         tk->fmt = fmt;
  668.                         tk->i_frame = 0;
  669.                         tk->p_frame = NULL;
  670.                         tk->p_es = es_out_Add( p_demux->out, &fmt );
  671.                         TAB_APPEND( p_sys->i_track, p_sys->track, tk );
  672.                     }
  673.                     else if( !strncmp( p_peek, ".raxfd", 4 ) )
  674.                     {
  675.                         int     i_version = GetWBE( &p_peek[4] );
  676.                         uint8_t *p_extra = NULL;
  677.                         msg_Dbg( p_demux, "    - audio version=%d", i_version );
  678.                         es_format_Init( &fmt, AUDIO_ES, 0 );
  679.                         if( i_version == 4 && stream_Peek( p_demux->s, &p_peek, 56 ) >= 56 )
  680.                         {
  681.                             fmt.audio.i_channels = GetWBE( &p_peek[54] );
  682.                             fmt.audio.i_rate = GetWBE( &p_peek[48] );
  683.                             if( stream_Peek( p_demux->s, &p_peek, 57 ) >= 57 )
  684.                             {
  685.                                 int i_extra = p_peek[56] + 1 + 4;
  686.                                 if( stream_Peek( p_demux->s, &p_peek, 57 + i_extra ) >= 57 + i_extra )
  687.                                 {
  688.                                     memcpy( &fmt.i_codec, &p_peek[57 + p_peek[56] + 1], 4 );
  689.                                 }
  690.                                 p_extra = &p_peek[57 + p_peek[56] + 1+ 4 + 3];
  691.                             }
  692.                         }
  693.                         else if( i_version == 5 && stream_Peek( p_demux->s, &p_peek, 70 ) >= 70 )
  694.                         {
  695.                             memcpy( &fmt.i_codec, &p_peek[66], 4 );
  696.                             fmt.audio.i_channels = GetWBE( &p_peek[60] );
  697.                             fmt.audio.i_rate = GetWBE( &p_peek[54] );
  698.                             p_extra = &p_peek[66+4+3+1];
  699.                         }
  700.                         msg_Dbg( p_demux, "    - audio codec=%4.4s channels=%d rate=%dHz",
  701.                                 (char*)&fmt.i_codec,
  702.                                 fmt.audio.i_channels, fmt.audio.i_rate );
  703.                         if( fmt.i_codec == VLC_FOURCC( 'd', 'n', 'e', 't' ) )
  704.                         {
  705.                             fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
  706.                         }
  707.                         else if( fmt.i_codec == VLC_FOURCC( 'r', 'a', 'a', 'c' ) ||
  708.                                  fmt.i_codec == VLC_FOURCC( 'r', 'a', 'c', 'p' ) )
  709.                         {
  710.                             int i_peek = p_extra - p_peek;
  711.                             if( stream_Peek( p_demux->s, &p_peek, i_peek + 4 ) >= i_peek + 4 )
  712.                             {
  713.                                 int i_extra = GetDWBE( &p_peek[i_peek] );
  714.                                 if( i_extra > 1 && i_peek + 4 + i_extra <= i_len &&
  715.                                     stream_Peek( p_demux->s, &p_peek, i_peek + 4 + i_extra ) >= i_peek + 4 + i_extra )
  716.                                 {
  717.                                     fmt.i_extra = i_extra - 1;
  718.                                     fmt.p_extra = malloc ( i_extra - 1 );
  719.                                     memcpy( fmt.p_extra, &p_peek[i_peek+4+1], i_extra - 1 );
  720.                                     msg_Dbg( p_demux, "        - extra data=%d", i_extra );
  721.                                     {
  722.                                         int i;
  723.                                         for( i = 0; i < fmt.i_extra; i++ )
  724.                                         {
  725.                                             msg_Dbg( p_demux, "          data[%d] = 0x%x", i,((uint8_t*)fmt.p_extra)[i] );
  726.                                         }
  727.                                     }
  728.                                 }
  729.                             }
  730.                             fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
  731.                         }
  732.                         if( fmt.i_codec != 0 )
  733.                         {
  734.                             tk = malloc( sizeof( real_track_t ) );
  735.                             tk->i_id = i_num;
  736.                             tk->fmt = fmt;
  737.                             tk->i_frame = 0;
  738.                             tk->p_frame = NULL;
  739.                             tk->p_es = es_out_Add( p_demux->out, &fmt );
  740.                             TAB_APPEND( p_sys->i_track, p_sys->track, tk );
  741.                         }
  742.                     }
  743.                 }
  744.                 stream_Read( p_demux->s, NULL, i_len );
  745.                 i_skip -= i_len;
  746.             }
  747.             i_skip -= 4;
  748.         }
  749.         else if( i_id == VLC_FOURCC('D','A','T','A') )
  750.         {
  751.             stream_Read( p_demux->s, header, 8 );
  752.             p_sys->i_data_offset    = stream_Tell( p_demux->s ) - 10;
  753.             p_sys->i_data_size      = i_size;
  754.             p_sys->i_data_packets_count = GetDWBE( header );
  755.             p_sys->i_data_packets   = 0;
  756.             p_sys->i_data_offset_next = GetDWBE( &header[4] );
  757.             msg_Dbg( p_demux, "    - packets count=%d next=%u",
  758.                      p_sys->i_data_packets_count,
  759.                      (uint32_t)p_sys->i_data_offset_next );
  760.             /* we have finished the header */
  761.             break;
  762.         }
  763.         else
  764.         {
  765.             /* unknow header */
  766.             msg_Dbg( p_demux, "unknown chunk" );
  767.         }
  768.         if( i_skip < 0 )
  769.         {
  770.             return VLC_EGENERIC;
  771.         }
  772.         stream_Read( p_demux->s, NULL, i_skip );
  773.     }
  774.     /* TODO read index if possible */
  775.     return VLC_SUCCESS;
  776. }