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

real.c

00001 /*****************************************************************************
00002  * real.c: Real demuxer.
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: real.c 13661 2005-12-10 15:41:01Z gbazin $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>                                      /* malloc(), free() */
00028 
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031 
00032 /*****************************************************************************
00033  * Module descriptor
00034  *****************************************************************************/
00035 static int  Open    ( vlc_object_t * );
00036 static void Close  ( vlc_object_t * );
00037 
00038 vlc_module_begin();
00039     set_description( _("Real demuxer" ) );
00040     set_capability( "demux2", 15 );
00041     set_category( CAT_INPUT );
00042     set_subcategory( SUBCAT_INPUT_DEMUX );
00043     set_callbacks( Open, Close );
00044     add_shortcut( "real" );
00045     add_shortcut( "rm" );
00046 vlc_module_end();
00047 
00048 /*****************************************************************************
00049  * Local prototypes
00050  *****************************************************************************/
00051 
00052 typedef struct
00053 {
00054     int         i_id;
00055     es_format_t fmt;
00056 
00057     es_out_id_t *p_es;
00058 
00059     int         i_frame;
00060     block_t     *p_frame;
00061 
00062     int         i_subpacket_h;
00063     int         i_subpacket_size;
00064     int         i_coded_frame_size;
00065     int         i_frame_size;
00066 
00067     int         i_subpacket;
00068     int         i_subpackets;
00069     block_t     **p_subpackets;
00070     int         i_out_subpacket;
00071 
00072 } real_track_t;
00073 
00074 struct demux_sys_t
00075 {
00076     int64_t  i_data_offset;
00077     int64_t  i_data_size;
00078     uint32_t i_data_packets_count;
00079     uint32_t i_data_packets;
00080     int64_t  i_data_offset_next;
00081 
00082     int          i_track;
00083     real_track_t **track;
00084 
00085     uint8_t buffer[65536];
00086 
00087     int64_t     i_pcr;
00088 };
00089 
00090 static int Demux( demux_t *p_demux );
00091 static int Control( demux_t *p_demux, int i_query, va_list args );
00092 
00093 static int HeaderRead( demux_t *p_demux );
00094 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num );
00095 
00096 /*****************************************************************************
00097  * Open
00098  *****************************************************************************/
00099 static int Open( vlc_object_t *p_this )
00100 {
00101     demux_t     *p_demux = (demux_t*)p_this;
00102     demux_sys_t *p_sys;
00103 
00104     uint8_t     *p_peek;
00105 
00106     if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) return VLC_EGENERIC;
00107     if( strncmp( (char *)p_peek, ".RMF", 4 ) ) return VLC_EGENERIC;
00108 
00109     /* Fill p_demux field */
00110     p_demux->pf_demux = Demux;
00111     p_demux->pf_control = Control;
00112     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00113     memset( p_sys, 0, sizeof( demux_sys_t ) );
00114     p_sys->i_data_offset = 0;
00115     p_sys->i_track = 0;
00116     p_sys->track   = NULL;
00117     p_sys->i_pcr   = 1;
00118 
00119 
00120     /* Parse the headers */
00121     if( HeaderRead( p_demux ) )
00122     {
00123         int i;
00124         msg_Err( p_demux, "invalid header" );
00125         for( i = 0; i < p_sys->i_track; i++ )
00126         {
00127             real_track_t *tk = p_sys->track[i];
00128 
00129             if( tk->p_es )
00130             {
00131                 es_out_Del( p_demux->out, tk->p_es );
00132             }
00133             free( tk );
00134         }
00135         if( p_sys->i_track > 0 )
00136         {
00137             free( p_sys->track );
00138         }
00139         free( p_sys );
00140         return VLC_EGENERIC;
00141     }
00142 
00143     return VLC_SUCCESS;
00144 }
00145 
00146 /*****************************************************************************
00147  * Close
00148  *****************************************************************************/
00149 static void Close( vlc_object_t *p_this )
00150 {
00151     demux_t *p_demux = (demux_t*)p_this;
00152     demux_sys_t *p_sys = p_demux->p_sys;
00153     int i;
00154 
00155     for( i = 0; i < p_sys->i_track; i++ )
00156     {
00157         real_track_t *tk = p_sys->track[i];
00158 
00159         if( tk->p_frame ) block_Release( tk->p_frame );
00160         es_format_Clean( &tk->fmt );
00161 
00162         while(  tk->i_subpackets-- )
00163         {
00164             if( tk->p_subpackets[tk->i_subpackets] )
00165                 block_Release( tk->p_subpackets[tk->i_subpackets] );
00166             if( !tk->i_subpackets ) free( tk->p_subpackets );
00167         }
00168 
00169         free( tk );
00170     }
00171 
00172     if( p_sys->i_track > 0 ) free( p_sys->track );
00173     free( p_sys );
00174 }
00175 
00176 
00177 /*****************************************************************************
00178  * Demux:
00179  *****************************************************************************/
00180 static int Demux( demux_t *p_demux )
00181 {
00182     demux_sys_t *p_sys = p_demux->p_sys;
00183     uint8_t     header[18];
00184     int         i_size, i_id, i_flags, i;
00185     int64_t     i_pts;
00186     real_track_t *tk = NULL;
00187     vlc_bool_t  b_selected;
00188 
00189     if( p_sys->i_data_packets >= p_sys->i_data_packets_count &&
00190         p_sys->i_data_packets_count )
00191     {
00192         if( stream_Read( p_demux->s, header, 18 ) < 18 )
00193         {
00194             return 0;
00195         }
00196         if( strncmp( (char *)header, "DATA", 4 ) )
00197         {
00198             return 0;
00199         }
00200         p_sys->i_data_offset = stream_Tell( p_demux->s ) - 18;
00201         p_sys->i_data_size   = GetDWBE( &header[4] );
00202         p_sys->i_data_packets_count = GetDWBE( &header[10] );
00203         p_sys->i_data_packets = 0;
00204         p_sys->i_data_offset_next = GetDWBE( &header[14] );
00205 
00206         msg_Dbg( p_demux, "entering new DATA packets=%d next=%u",
00207                  p_sys->i_data_packets_count,
00208                  (uint32_t)p_sys->i_data_offset_next );
00209     }
00210 
00211     if( stream_Read( p_demux->s, header, 12 ) < 12 ) return 0;
00212 
00213     i_size = GetWBE( &header[2] ) - 12;
00214     i_id   = GetWBE( &header[4] );
00215     i_pts  = 1000 * GetDWBE( &header[6] );
00216     i_pts += 1000; /* Avoid 0 pts */
00217     i_flags= header[11]; /* flags 0x02 -> keyframe */
00218 
00219 #if 0
00220     msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u",
00221              p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) );
00222 #endif
00223 
00224     p_sys->i_data_packets++;
00225 
00226     stream_Read( p_demux->s, p_sys->buffer, i_size );
00227 
00228     for( i = 0; i < p_sys->i_track; i++ )
00229     {
00230         if( p_sys->track[i]->i_id == i_id ) tk = p_sys->track[i];
00231     }
00232 
00233     if( tk == NULL )
00234     {
00235         msg_Warn( p_demux, "unknown track id(0x%x)", i_id );
00236         return 1;
00237     }
00238     es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b_selected );
00239 
00240     if( tk->fmt.i_cat == VIDEO_ES && b_selected )
00241     {
00242         uint8_t *p = p_sys->buffer;
00243 
00244         while( p < &p_sys->buffer[i_size - 2] )
00245         {
00246             uint8_t h = *p++;
00247             int     i_len = 0;
00248             int     i_copy;
00249             int     i_subseq = 0;
00250             int     i_seqnum = 0;
00251             int     i_offset = 0;
00252 
00253             if( (h&0xc0) == 0x40 )
00254             {
00255                 /* Short header */
00256                 p++;
00257                 i_len = &p_sys->buffer[i_size] - p;
00258             }
00259             else
00260             {
00261                 if( (h&0x40) == 0 )
00262                 {
00263                     i_subseq = (*p++)&0x7f;
00264                 }
00265                 i_len = (p[0] << 8)|p[1]; p += 2;
00266                 if( (i_len&0xc000) == 0 )
00267                 {
00268                     i_len <<= 16;
00269                     i_len |= (p[0] << 8)|p[1]; p += 2;
00270                     i_len &= 0x3fffffff;
00271                 }
00272                 else
00273                 {
00274                     i_len &= 0x3fff;
00275                 }
00276 
00277                 i_offset = (p[0] << 8)|p[1]; p += 2;
00278                 if( (i_offset&0xc000) == 0 )
00279                 {
00280                     i_offset <<= 16;
00281                     i_offset |= (p[0] << 8)|p[1]; p += 2;
00282                     i_offset &= 0x3fffffff;
00283                 }
00284                 else
00285                 {
00286                     i_offset &= 0x3fff;
00287                 }
00288                 i_seqnum = *p++;
00289             }
00290 
00291             i_copy = i_len - i_offset;
00292             if( i_copy > &p_sys->buffer[i_size] - p )
00293             {
00294                 i_copy = &p_sys->buffer[i_size] - p;
00295             }
00296             else if( i_copy < 0 )
00297             {
00298                 break;
00299             }
00300 
00301             msg_Dbg( p_demux, "    - len=%d offset=%d size=%d subseq=%d seqnum=%d",
00302                      i_len, i_offset, i_copy, i_subseq, i_seqnum );
00303 
00304             if( (h&0xc0) == 0x80 )
00305             {
00306                 /* last fragment -> fixes */
00307                 i_copy = i_offset;
00308                 i_offset = i_len - i_copy;
00309                 msg_Dbg( p_demux, "last fixing copy=%d offset=%d",
00310                          i_copy, i_offset );
00311             }
00312 
00313             if( tk->p_frame &&
00314                 ( tk->p_frame->i_dts != i_pts ||
00315                   tk->i_frame != i_len ) )
00316             {
00317                 msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer );
00318 
00319                 if( p_sys->i_pcr < tk->p_frame->i_dts )
00320                 {
00321                     p_sys->i_pcr = tk->p_frame->i_dts;
00322 
00323                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00324                                     (int64_t)p_sys->i_pcr );
00325                 }
00326                 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
00327 
00328                 tk->i_frame = 0;
00329                 tk->p_frame = NULL;
00330             }
00331 
00332             if( (h&0xc0) != 0x80 && (h&0xc0) != 0x00 && !tk->p_frame )
00333             {
00334                 /* no fragment */
00335                 i_len = i_copy;
00336                 i_offset = 0;
00337             }
00338 
00339 
00340             if( tk->p_frame == NULL )
00341             {
00342                 msg_Dbg( p_demux, "new frame size=%d", i_len );
00343                 tk->i_frame = i_len;
00344                 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
00345                 {
00346                     return -1;
00347                 }
00348                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
00349                 tk->p_frame->i_dts = i_pts;
00350                 tk->p_frame->i_pts = i_pts;
00351 
00352                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
00353                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 0;      /* chunk counts */
00354             }
00355 
00356             if( i_offset < tk->i_frame)
00357             {
00358                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
00359 
00360                 msg_Dbg( p_demux, "copying new buffer n=%d offset=%d copy=%d",
00361                          i_ck, i_offset, i_copy );
00362 
00363                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00364 
00365                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00366             }
00367 
00368             p += i_copy;
00369 
00370             if( (h&0xc0) != 0x80 )
00371             {
00372                 break;
00373             }
00374 
00375 #if 0
00376             if( tk->p_frame )
00377             {
00378                 /* append data */
00379                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
00380 
00381                 if( (h&0xc0) == 0x80 )
00382                 {
00383                     /* last fragment */
00384                     i_copy = i_offset;
00385                     i_offset = i_len - i_offset;
00386 
00387                     ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00388                     memcpy( &tk->p_frame->p_buffer[i_offset+ 8], p, i_copy );
00389                     p += i_copy;
00390 
00391                     if( p_sys->i_pcr < tk->p_frame->i_dts )
00392                     {
00393                         p_sys->i_pcr = tk->p_frame->i_dts;
00394                         es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00395                                         (int64_t)p_sys->i_pcr );
00396                     }
00397                     es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
00398 
00399                     tk->i_frame = 0;
00400                     tk->p_frame = NULL;
00401 
00402                     continue;
00403                 }
00404 
00405                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00406                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00407                 break;
00408             }
00409 
00410             if( (h&0xc0) != 0x00 )
00411             {
00412                 block_t *p_frame;
00413 
00414                 /* not fragmented */
00415                 if( !( p_frame = block_New( p_demux, i_copy + 8 + 8 ) ) )
00416                 {
00417                     return -1;
00418                 }
00419                 p_frame->i_dts = i_pts;
00420                 p_frame->i_pts = i_pts;
00421 
00422                 ((uint32_t*)p_frame->p_buffer)[0] = i_copy;
00423                 ((uint32_t*)p_frame->p_buffer)[1] = 1;
00424                 ((uint32_t*)(p_frame->p_buffer+i_copy+8))[0] = 0;
00425                 memcpy( &p_frame->p_buffer[8], p, i_copy );
00426 
00427                 p += i_copy;
00428 
00429                 if( p_sys->i_pcr < p_frame->i_dts )
00430                 {
00431                     p_sys->i_pcr = p_frame->i_dts;
00432                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00433                                     (int64_t)p_sys->i_pcr );
00434                 }
00435                 es_out_Send( p_demux->out, tk->p_es, p_frame );
00436             }
00437             else
00438             {
00439                 /* First fragment */
00440                 tk->i_frame = i_len;
00441                 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
00442                 {
00443                     return -1;
00444                 }
00445                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
00446                 tk->p_frame->i_dts = i_pts;
00447                 tk->p_frame->i_pts = i_pts;
00448 
00449                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
00450                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 1;      /* chunk counts */
00451                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[0] = i_offset;
00452                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00453 
00454                 break;
00455             }
00456 #endif
00457         }
00458     }
00459     else if( tk->fmt.i_cat == AUDIO_ES && b_selected )
00460     {
00461         /* Set PCR */
00462         if( p_sys->i_pcr < i_pts )
00463         {
00464             p_sys->i_pcr = i_pts;
00465             es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00466                             (int64_t)p_sys->i_pcr );
00467         }
00468 
00469         if( tk->fmt.i_codec == VLC_FOURCC( 'm', 'p', '4', 'a' ) )
00470         {
00471             int     i_sub = (p_sys->buffer[1] >> 4)&0x0f;
00472             uint8_t *p_sub = &p_sys->buffer[2+2*i_sub];
00473 
00474             int i;
00475             for( i = 0; i < i_sub; i++ )
00476             {
00477                 int i_sub_size = GetWBE( &p_sys->buffer[2+i*2]);
00478                 block_t *p_block = block_New( p_demux, i_sub_size );
00479                 if( p_block )
00480                 {
00481                     memcpy( p_block->p_buffer, p_sub, i_sub_size );
00482                     p_sub += i_sub_size;
00483 
00484                     p_block->i_dts =
00485                     p_block->i_pts = ( i == 0 ? i_pts : 0 );
00486 
00487                     es_out_Send( p_demux->out, tk->p_es, p_block );
00488                 }
00489             }
00490         }
00491         else if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
00492                  tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
00493         {
00494             uint8_t *p_buf = p_sys->buffer;
00495             int y = tk->i_subpacket / (tk->i_frame_size /tk->i_subpacket_size);
00496             int i_index, i;
00497 
00498             /* Sanity check */
00499             if( i_flags & 2 ) y = tk->i_subpacket = 0;
00500 
00501             if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) )
00502             for( i = 0; i < tk->i_frame_size / tk->i_subpacket_size; i++ )
00503             {
00504                 block_t *p_block = block_New( p_demux, tk->i_subpacket_size );
00505                 memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size );
00506                 p_buf += tk->i_subpacket_size;
00507 
00508                 i_index = tk->i_subpacket_h * i +
00509                     ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1);
00510 
00511                 p_block->i_dts = p_block->i_pts = i_pts;
00512                 tk->p_subpackets[i_index] = p_block;
00513                 tk->i_subpacket++;
00514             }
00515 
00516             if( tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
00517             for( i = 0; i < tk->i_subpacket_h / 2; i++ )
00518             {
00519                 block_t *p_block = block_New( p_demux, tk->i_coded_frame_size);
00520                 memcpy( p_block->p_buffer, p_buf, tk->i_coded_frame_size );
00521                 p_buf += tk->i_coded_frame_size;
00522 
00523                 i_index = (i * 2 * tk->i_frame_size) /
00524                     tk->i_coded_frame_size + y;
00525 
00526                 p_block->i_dts = p_block->i_pts = i_pts;
00527                 tk->p_subpackets[i_index] = p_block;
00528                 tk->i_subpacket++;
00529             }
00530 
00531             while( tk->i_out_subpacket != tk->i_subpackets &&
00532                    tk->p_subpackets[tk->i_out_subpacket] )
00533             {
00534                 block_t *p_block = tk->p_subpackets[tk->i_out_subpacket];
00535                 tk->p_subpackets[tk->i_out_subpacket] = 0;
00536 
00537                 if( tk->i_out_subpacket ) p_block->i_dts = p_block->i_pts = 0;
00538                 es_out_Send( p_demux->out, tk->p_es, p_block );
00539 
00540                 tk->i_out_subpacket++;
00541             }
00542 
00543             if( tk->i_subpacket == tk->i_subpackets &&
00544                 tk->i_out_subpacket != tk->i_subpackets )
00545             {
00546                 msg_Warn( p_demux, "i_subpacket != i_out_subpacket, "
00547                           "this shouldn't happen" );
00548             }
00549 
00550             if( tk->i_subpacket == tk->i_subpackets )
00551             {
00552                 tk->i_subpacket = 0;
00553                 tk->i_out_subpacket = 0;
00554             }
00555         }
00556         else
00557         {
00558             block_t *p_block = block_New( p_demux, i_size );
00559 
00560             if( tk->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', ' ' ) )
00561             {
00562                 uint8_t *src = p_sys->buffer;
00563                 uint8_t *dst = p_block->p_buffer;
00564 
00565                 /* byte swap data */
00566                 while( dst < &p_block->p_buffer[i_size- 1])
00567                 {
00568                     *dst++ = src[1];
00569                     *dst++ = src[0];
00570 
00571                     src += 2;
00572                 }
00573             }
00574             else
00575             {
00576                 memcpy( p_block->p_buffer, p_sys->buffer, i_size );
00577             }
00578             p_block->i_dts = p_block->i_pts = i_pts;
00579             es_out_Send( p_demux->out, tk->p_es, p_block );
00580         }
00581     }
00582 
00583 
00584     return 1;
00585 }
00586 
00587 /*****************************************************************************
00588  * Control:
00589  *****************************************************************************/
00590 static int Control( demux_t *p_demux, int i_query, va_list args )
00591 {
00592 #if 0
00593     demux_sys_t *p_sys = p_demux->p_sys;
00594     double f, *pf;
00595     int64_t i64, *pi64;
00596 
00597     switch( i_query )
00598     {
00599         case DEMUX_GET_POSITION:
00600             pf = (double*) va_arg( args, double* );
00601             i64 = stream_Size( p_demux->s );
00602             if( i64 > 0 )
00603             {
00604                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
00605             }
00606             else
00607             {
00608                 *pf = 0.0;
00609             }
00610             return VLC_SUCCESS;
00611         case DEMUX_SET_POSITION:
00612             f = (double) va_arg( args, double );
00613             i64 = stream_Size( p_demux->s );
00614 
00615             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00616 
00617             return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
00618 
00619         case DEMUX_GET_TIME:
00620             pi64 = (int64_t*)va_arg( args, int64_t * );
00621             if( p_sys->i_mux_rate > 0 )
00622             {
00623                 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
00624                 return VLC_SUCCESS;
00625             }
00626             *pi64 = 0;
00627             return VLC_EGENERIC;
00628 
00629         case DEMUX_GET_LENGTH:
00630             pi64 = (int64_t*)va_arg( args, int64_t * );
00631             if( p_sys->i_mux_rate > 0 )
00632             {
00633                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
00634                 return VLC_SUCCESS;
00635             }
00636             *pi64 = 0;
00637             return VLC_EGENERIC;
00638 
00639         case DEMUX_SET_TIME:
00640         case DEMUX_GET_FPS:
00641         default:
00642             return VLC_EGENERIC;
00643     }
00644 #endif
00645     return VLC_EGENERIC;
00646 }
00647 
00648 /*****************************************************************************
00649  * HeaderRead:
00650  *****************************************************************************/
00651 static int HeaderRead( demux_t *p_demux )
00652 {
00653     demux_sys_t *p_sys = p_demux->p_sys;
00654     uint8_t header[100];    /* FIXME */
00655 
00656     uint32_t    i_id;
00657     uint32_t    i_size;
00658     int64_t     i_skip;
00659     int         i_version;
00660 
00661     for( ;; )
00662     {
00663         /* Read the header */
00664         if( stream_Read( p_demux->s, header, 10 ) < 10 )
00665         {
00666             return VLC_EGENERIC;
00667         }
00668         i_id        = VLC_FOURCC( header[0], header[1], header[2], header[3] );
00669         i_size      = GetDWBE( &header[4] );
00670         i_version   = GetWBE( &header[8] );
00671 
00672         msg_Dbg( p_demux, "object %4.4s size=%d version=%d",
00673                  (char*)&i_id, i_size, i_version );
00674 
00675         if( i_size < 10 )
00676         {
00677             msg_Dbg( p_demux, "invalid size for object %4.4s", (char*)&i_id );
00678             return VLC_EGENERIC;
00679         }
00680         i_skip = i_size - 10;
00681 
00682         if( i_id == VLC_FOURCC('.','R','M','F') )
00683         {
00684             if( stream_Read( p_demux->s, header, 8 ) < 8 ) return VLC_EGENERIC;
00685             msg_Dbg( p_demux, "    - file version=0x%x num headers=%d",
00686                      GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
00687 
00688             i_skip -= 8;
00689         }
00690         else if( i_id == VLC_FOURCC('P','R','O','P') )
00691         {
00692             int i_flags;
00693 
00694             if( stream_Read(p_demux->s, header, 40) < 40 ) return VLC_EGENERIC;
00695 
00696             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d",
00697                      GetDWBE(&header[0]), GetDWBE(&header[4]) );
00698             msg_Dbg( p_demux, "    - max packet size=%d avg bitrate=%d",
00699                      GetDWBE(&header[8]), GetDWBE(&header[12]) );
00700             msg_Dbg( p_demux, "    - packets count=%d", GetDWBE(&header[16]) );
00701             msg_Dbg( p_demux, "    - duration=%d ms", GetDWBE(&header[20]) );
00702             msg_Dbg( p_demux, "    - preroll=%d ms", GetDWBE(&header[24]) );
00703             msg_Dbg( p_demux, "    - index offset=%d", GetDWBE(&header[28]) );
00704             msg_Dbg( p_demux, "    - data offset=%d", GetDWBE(&header[32]) );
00705             msg_Dbg( p_demux, "    - num streams=%d", GetWBE(&header[36]) );
00706             i_flags = GetWBE(&header[38]);
00707             msg_Dbg( p_demux, "    - flags=0x%x %s%s%s",
00708                      i_flags,
00709                      i_flags&0x0001 ? "PN_SAVE_ENABLED " : "",
00710                      i_flags&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
00711                      i_flags&0x0004 ? "PN_LIVE_BROADCAST" : "" );
00712             i_skip -= 40;
00713         }
00714         else if( i_id == VLC_FOURCC('C','O','N','T') )
00715         {
00716             int i_len;
00717             char *psz;
00718 
00719             stream_Read( p_demux->s, header, 2 );
00720             if( ( i_len = GetWBE( header ) ) > 0 )
00721             {
00722                 psz = malloc( i_len + 1 );
00723                 stream_Read( p_demux->s, psz, i_len );
00724                 psz[i_len] = '\0';
00725 
00726                 msg_Dbg( p_demux, "    - title=`%s'", psz );
00727                 free( psz );
00728                 i_skip -= i_len;
00729             }
00730             i_skip -= 2;
00731 
00732             stream_Read( p_demux->s, header, 2 );
00733             if( ( i_len = GetWBE( header ) ) > 0 )
00734             {
00735                 psz = malloc( i_len + 1 );
00736                 stream_Read( p_demux->s, psz, i_len );
00737                 psz[i_len] = '\0';
00738 
00739                 msg_Dbg( p_demux, "    - author=`%s'", psz );
00740                 free( psz );
00741                 i_skip -= i_len;
00742             }
00743             i_skip -= 2;
00744 
00745             stream_Read( p_demux->s, header, 2 );
00746             if( ( i_len = GetWBE( header ) ) > 0 )
00747             {
00748                 psz = malloc( i_len + 1 );
00749                 stream_Read( p_demux->s, psz, i_len );
00750                 psz[i_len] = '\0';
00751 
00752                 msg_Dbg( p_demux, "    - copyright=`%s'", psz );
00753                 free( psz );
00754                 i_skip -= i_len;
00755             }
00756             i_skip -= 2;
00757 
00758             stream_Read( p_demux->s, header, 2 );
00759             if( ( i_len = GetWBE( header ) ) > 0 )
00760             {
00761                 psz = malloc( i_len + 1 );
00762                 stream_Read( p_demux->s, psz, i_len );
00763                 psz[i_len] = '\0';
00764 
00765                 msg_Dbg( p_demux, "    - comment=`%s'", psz );
00766                 free( psz );
00767                 i_skip -= i_len;
00768             }
00769             i_skip -= 2;
00770         }
00771         else if( i_id == VLC_FOURCC('M','D','P','R') )
00772         {
00773             /* Media properties header */
00774             int  i_num;
00775             int  i_len;
00776             char *psz;
00777 
00778             if( stream_Read(p_demux->s, header, 30) < 30 ) return VLC_EGENERIC;
00779             i_num = GetWBE( header );
00780             msg_Dbg( p_demux, "    - id=0x%x", i_num );
00781             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d",
00782                      GetDWBE(&header[2]), GetDWBE(&header[6]) );
00783             msg_Dbg( p_demux, "    - max packet size=%d avg packet size=%d",
00784                      GetDWBE(&header[10]), GetDWBE(&header[14]) );
00785             msg_Dbg( p_demux, "    - start time=%d", GetDWBE(&header[18]) );
00786             msg_Dbg( p_demux, "    - preroll=%d", GetDWBE(&header[22]) );
00787             msg_Dbg( p_demux, "    - duration=%d", GetDWBE(&header[26]) );
00788             i_skip -= 30;
00789 
00790             stream_Read( p_demux->s, header, 1 );
00791             if( ( i_len = header[0] ) > 0 )
00792             {
00793                 psz = malloc( i_len + 1 );
00794                 stream_Read( p_demux->s, psz, i_len );
00795                 psz[i_len] = '\0';
00796 
00797                 msg_Dbg( p_demux, "    - name=`%s'", psz );
00798                 free( psz );
00799                 i_skip -= i_len;
00800             }
00801             i_skip--;
00802 
00803             stream_Read( p_demux->s, header, 1 );
00804             if( ( i_len = header[0] ) > 0 )
00805             {
00806                 psz = malloc( i_len + 1 );
00807                 stream_Read( p_demux->s, psz, i_len );
00808                 psz[i_len] = '\0';
00809 
00810                 msg_Dbg( p_demux, "    - mime=`%s'", psz );
00811                 free( psz );
00812                 i_skip -= i_len;
00813             }
00814             i_skip--;
00815 
00816             stream_Read( p_demux->s, header, 4 );
00817             if( ( i_len = GetDWBE( header ) ) > 0 )
00818             {
00819                 ReadCodecSpecificData( p_demux, i_len, i_num );
00820                 stream_Read( p_demux->s, NULL, i_len );
00821 
00822                 i_skip -= i_len;
00823             }
00824             i_skip -= 4;
00825         }
00826         else if( i_id == VLC_FOURCC('D','A','T','A') )
00827         {
00828             stream_Read( p_demux->s, header, 8 );
00829 
00830             p_sys->i_data_offset    = stream_Tell( p_demux->s ) - 10;
00831             p_sys->i_data_size      = i_size;
00832             p_sys->i_data_packets_count = GetDWBE( header );
00833             p_sys->i_data_packets   = 0;
00834             p_sys->i_data_offset_next = GetDWBE( &header[4] );
00835 
00836             msg_Dbg( p_demux, "    - packets count=%d next=%u",
00837                      p_sys->i_data_packets_count,
00838                      (uint32_t)p_sys->i_data_offset_next );
00839 
00840             /* we have finished the header */
00841             break;
00842         }
00843         else
00844         {
00845             /* unknow header */
00846             msg_Dbg( p_demux, "unknown chunk" );
00847         }
00848 
00849         if( i_skip < 0 ) return VLC_EGENERIC;
00850         stream_Read( p_demux->s, NULL, i_skip );
00851     }
00852 
00853     /* TODO read index if possible */
00854 
00855     return VLC_SUCCESS;
00856 }
00857 
00858 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num )
00859 {
00860     demux_sys_t *p_sys = p_demux->p_sys;
00861     es_format_t fmt;
00862     real_track_t *tk;
00863     uint8_t *p_peek;
00864 
00865     msg_Dbg( p_demux, "    - specific data len=%d", i_len );
00866     if( stream_Peek(p_demux->s, &p_peek, i_len) < i_len ) return VLC_EGENERIC;
00867 
00868     if( !strncmp( (char *)&p_peek[4], "VIDO", 4 ) )
00869     {
00870         es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( p_peek[8], p_peek[9],
00871                         p_peek[10], p_peek[11] ) );
00872         fmt.video.i_width = GetWBE( &p_peek[12] );
00873         fmt.video.i_height= GetWBE( &p_peek[14] );
00874 
00875         fmt.i_extra = 8;
00876         fmt.p_extra = malloc( 8 );
00877         ((uint32_t*)fmt.p_extra)[0] = GetDWBE( &p_peek[26] );
00878         ((uint32_t*)fmt.p_extra)[1] = GetDWBE( &p_peek[30] );
00879 
00880         msg_Dbg( p_demux, "    - video 0x%08x 0x%08x",
00881                  ((uint32_t*)fmt.p_extra)[0], ((uint32_t*)fmt.p_extra)[1] );
00882 
00883         if( GetDWBE( &p_peek[30] ) == 0x10003000 ||
00884             GetDWBE( &p_peek[30] ) == 0x10003001 )
00885         {
00886             fmt.i_codec = VLC_FOURCC( 'R','V','1','3' );
00887         }
00888 
00889         msg_Dbg( p_demux, "    - video %4.4s %dx%d",
00890                  (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
00891 
00892         tk = malloc( sizeof( real_track_t ) );
00893         tk->i_id = i_num;
00894         tk->fmt = fmt;
00895         tk->i_frame = 0;
00896         tk->p_frame = NULL;
00897         tk->p_es = es_out_Add( p_demux->out, &fmt );
00898 
00899         TAB_APPEND( p_sys->i_track, p_sys->track, tk );
00900     }
00901     else if( !strncmp( (char *)p_peek, ".ra\xfd", 4 ) )
00902     {
00903         int i_version = GetWBE( &p_peek[4] );
00904         int i_header_size, i_flavor, i_coded_frame_size, i_subpacket_h;
00905         int i_frame_size, i_subpacket_size;
00906 
00907         msg_Dbg( p_demux, "    - audio version=%d", i_version );
00908 
00909         p_peek += 6;
00910         es_format_Init( &fmt, AUDIO_ES, 0 );
00911 
00912         if( i_version == 3 )
00913         {
00914             msg_Dbg( p_demux, "    - audio version 3 is not supported!" );
00915             return VLC_EGENERIC;
00916         }
00917 
00918         p_peek += 2; /* 00 00 */
00919         p_peek += 4; /* .ra4 or .ra5 */
00920         p_peek += 4; /* ?? */
00921         p_peek += 2; /* version (4 or 5) */
00922         i_header_size = GetDWBE( p_peek ); p_peek += 4; /* header size */
00923         i_flavor = GetWBE( p_peek ); p_peek += 2; /* codec flavor */
00924         i_coded_frame_size = GetDWBE( p_peek ); p_peek += 4;
00925         p_peek += 4; /* ?? */
00926         p_peek += 4; /* ?? */
00927         p_peek += 4; /* ?? */
00928         i_subpacket_h = GetWBE( p_peek ); p_peek += 2;
00929         i_frame_size = GetWBE( p_peek ); p_peek += 2;
00930         i_subpacket_size = GetWBE( p_peek ); p_peek += 2;
00931         p_peek += 2; /* ?? */
00932 
00933         if( i_version == 5 ) p_peek += 6; /* 0, srate, 0 */
00934 
00935         fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2;
00936         p_peek += 2; /* ?? */
00937         fmt.audio.i_bitspersample = GetWBE( p_peek ); p_peek += 2;
00938         fmt.audio.i_channels = GetWBE( p_peek ); p_peek += 2;
00939         fmt.audio.i_blockalign = i_frame_size;
00940 
00941         if( i_version == 5 )
00942         {
00943             p_peek += 4; /* genr */
00944             memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4;
00945         }
00946         else
00947         {
00948             p_peek += p_peek[0] + 1; /* descr 1 */
00949             memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 ); /* descr 2 */
00950             p_peek += p_peek[0] + 1;
00951         }
00952 
00953         msg_Dbg( p_demux, "    - audio codec=%4.4s channels=%d rate=%dHz",
00954                  (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate );
00955 
00956         p_peek += 3; /* ?? */
00957         if( i_version == 5 ) p_peek++;
00958 
00959         switch( fmt.i_codec )
00960         {
00961         case VLC_FOURCC( 'd', 'n', 'e', 't' ):
00962             fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
00963             break;
00964 
00965         case VLC_FOURCC( 'r', 'a', 'a', 'c' ):
00966         case VLC_FOURCC( 'r', 'a', 'c', 'p' ):
00967             fmt.i_extra = GetDWBE( p_peek ); p_peek += 4;
00968             if( fmt.i_extra > 0 ) { fmt.i_extra--; p_peek++; }
00969             if( fmt.i_extra > 0 )
00970             {
00971                 fmt.p_extra = malloc( fmt.i_extra );
00972                 memcpy( fmt.p_extra, p_peek, fmt.i_extra );
00973             }
00974 
00975             fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
00976             break;
00977 
00978         case VLC_FOURCC('c','o','o','k'):
00979             fmt.audio.i_blockalign = i_subpacket_size;
00980             if( !(fmt.i_extra = GetDWBE( p_peek )) ) break;
00981             fmt.p_extra = malloc( fmt.i_extra );
00982             memcpy( fmt.p_extra, p_peek + 4, fmt.i_extra );
00983             break;
00984 
00985         case VLC_FOURCC('2','8','_','8'):
00986             fmt.audio.i_blockalign = i_coded_frame_size;
00987             break;
00988 
00989         default:
00990             msg_Dbg( p_demux, "    - unknown audio codec=%4.4s",
00991                      (char*)&fmt.i_codec );
00992             break;
00993         }
00994 
00995         if( fmt.i_codec != 0 )
00996         {
00997             int i;
00998 
00999             msg_Dbg( p_demux, "        - extra data=%d", fmt.i_extra );
01000 
01001             tk = malloc( sizeof( real_track_t ) );
01002             tk->i_id = i_num;
01003             tk->fmt = fmt;
01004             tk->i_frame = 0;
01005             tk->p_frame = NULL;
01006 
01007             tk->i_subpacket_h = i_subpacket_h;
01008             tk->i_subpacket_size = i_subpacket_size;
01009             tk->i_coded_frame_size = i_coded_frame_size;
01010             tk->i_frame_size = i_frame_size;
01011 
01012             tk->i_out_subpacket = 0;
01013             tk->i_subpacket = 0;
01014             tk->i_subpackets = 0;
01015             tk->p_subpackets = NULL;
01016             if( fmt.i_codec == VLC_FOURCC('c','o','o','k') )
01017             {
01018                 tk->i_subpackets =
01019                     i_subpacket_h * i_frame_size / tk->i_subpacket_size;
01020                 tk->p_subpackets =
01021                     malloc( tk->i_subpackets * sizeof(block_t *) );
01022             }
01023             else if( fmt.i_codec == VLC_FOURCC('2','8','_','8') )
01024             {
01025                 tk->i_subpackets =
01026                     i_subpacket_h * i_frame_size / tk->i_coded_frame_size;
01027                 tk->p_subpackets =
01028                     malloc( tk->i_subpackets * sizeof(block_t *) );
01029             }
01030 
01031             for( i = 0; i < tk->i_subpackets; i++ ) tk->p_subpackets[i] = NULL;
01032 
01033             tk->p_es = es_out_Add( p_demux->out, &fmt );
01034 
01035             TAB_APPEND( p_sys->i_track, p_sys->track, tk );
01036         }
01037     }
01038 
01039     return VLC_SUCCESS;
01040 }

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