]> git.sesse.net Git - vlc/blob - modules/demux/real.c
cb683debcde7be45fbb491175be2cba79bc1b3a6
[vlc] / modules / demux / real.c
1 /*****************************************************************************
2  * real.c: Real demuxer.
3  *****************************************************************************
4  * Copyright (C) 2004, 2006-2007 the VideoLAN team
5  * $Id$
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 /**
25  * Status of this demuxer:
26  * Real Media format
27  * -----------------
28  *
29  * version v3 w/ 14_4/lpcJ is ok.
30  * version v4/5: - atrac3 is ok.
31  *               - cook is ok.
32  *               - raac, racp are ok.
33  *               - dnet is twisted "The byte order of the data is reversed
34  *                                  from standard AC3"
35  *               - 28_8 seem problematic.
36  *               - sipr should be fine, but our decoder suxx :)
37  *               - ralf is unsupported, but hardly any sample exist.
38  *               - mp3 is unsupported, one sample exists...
39  *
40  * Real Audio Only
41  * ---------------
42  * Not supported...
43  */
44
45 /*****************************************************************************
46  * Preamble
47  *****************************************************************************/
48 #ifdef HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <vlc/vlc.h>
53 #include <vlc_plugin.h>
54
55
56 #include <vlc_demux.h>
57 #include <vlc_charset.h>
58 #include <vlc_meta.h>
59
60 /*****************************************************************************
61  * Module descriptor
62  *****************************************************************************/
63 static int  Open    ( vlc_object_t * );
64 static void Close  ( vlc_object_t * );
65
66 vlc_module_begin();
67     set_description( N_("Real demuxer" ) );
68     set_capability( "demux", 15 );
69     set_category( CAT_INPUT );
70     set_subcategory( SUBCAT_INPUT_DEMUX );
71     set_callbacks( Open, Close );
72     add_shortcut( "real" );
73     add_shortcut( "rm" );
74 vlc_module_end();
75
76 /*****************************************************************************
77  * Local prototypes
78  *****************************************************************************/
79
80 typedef struct
81 {
82     int         i_id;
83     es_format_t fmt;
84
85     es_out_id_t *p_es;
86
87     int         i_frame;
88     block_t     *p_frame;
89
90     int         i_subpacket_h;
91     int         i_subpacket_size;
92     int         i_coded_frame_size;
93     int         i_frame_size;
94
95     int         i_subpacket;
96     int         i_subpackets;
97     block_t     **p_subpackets;
98     int64_t        *p_subpackets_timecode;
99     int         i_out_subpacket;
100
101 } real_track_t;
102
103 typedef struct
104 {
105     uint32_t file_offset;
106     uint32_t time_offset;
107     uint32_t frame_index;
108 } rm_index_t;
109
110 struct demux_sys_t
111 {
112     int64_t  i_data_offset;
113     int64_t  i_data_size;
114     uint32_t i_data_packets_count;
115     uint32_t i_data_packets;
116     int64_t  i_data_offset_next;
117
118     int  i_our_duration;
119     int  i_mux_rate;
120
121     char* psz_title;
122     char* psz_artist;
123     char* psz_copyright;
124     char* psz_description;
125
126     int          i_track;
127     real_track_t **track;
128
129     uint8_t buffer[65536];
130
131     int64_t     i_pcr;
132     vlc_meta_t *p_meta;
133
134     int64_t i_index_offset;
135     int        b_seek;
136     rm_index_t * p_index;
137 };
138
139 static int Demux( demux_t *p_demux );
140 static int Control( demux_t *p_demux, int i_query, va_list args );
141
142 static int HeaderRead( demux_t *p_demux );
143 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num );
144
145 /*****************************************************************************
146  * Open
147  *****************************************************************************/
148 static int Open( vlc_object_t *p_this )
149 {
150     demux_t     *p_demux = (demux_t*)p_this;
151     demux_sys_t *p_sys;
152
153     const uint8_t *p_peek;
154
155     if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) return VLC_EGENERIC;
156     if( !memcmp( p_peek, ".ra", 3 ) )
157     {
158         msg_Warn( p_demux, ".ra files unsuported" );
159         return VLC_EGENERIC;
160     }
161     if( memcmp( p_peek, ".RMF", 4 ) ) return VLC_EGENERIC;
162
163     /* Fill p_demux field */
164     p_demux->pf_demux = Demux;
165     p_demux->pf_control = Control;
166
167     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
168     if( p_sys == NULL )
169         return VLC_ENOMEM;
170
171     memset( p_sys, 0, sizeof( demux_sys_t ) );
172
173     p_sys->i_data_offset = 0;
174     p_sys->i_track = 0;
175     p_sys->track   = NULL;
176     p_sys->i_pcr   = 1;
177
178     p_sys->b_seek  = 0;
179
180     /* Parse the headers */
181     if( HeaderRead( p_demux ) )
182     {
183         int i;
184         msg_Err( p_demux, "invalid header" );
185         for( i = 0; i < p_sys->i_track; i++ )
186         {
187             real_track_t *tk = p_sys->track[i];
188
189             if( tk->p_es )
190             {
191                 es_out_Del( p_demux->out, tk->p_es );
192             }
193             free( tk );
194         }
195         if( p_sys->i_track > 0 )
196         {
197             free( p_sys->track );
198         }
199         free( p_sys );
200         return VLC_EGENERIC;
201     }
202
203     return VLC_SUCCESS;
204 }
205
206 /*****************************************************************************
207  * Close
208  *****************************************************************************/
209 static void Close( vlc_object_t *p_this )
210 {
211     demux_t *p_demux = (demux_t*)p_this;
212     demux_sys_t *p_sys = p_demux->p_sys;
213     int i;
214
215     for( i = 0; i < p_sys->i_track; i++ )
216     {
217         real_track_t *tk = p_sys->track[i];
218         int j = tk->i_subpackets;
219
220         if( tk->p_frame ) block_Release( tk->p_frame );
221         es_format_Clean( &tk->fmt );
222
223         while(  j-- )
224         {
225             if( tk->p_subpackets[ j ] )
226                 block_Release( tk->p_subpackets[ j ] );
227         }
228         if( tk->i_subpackets )
229         {
230             free( tk->p_subpackets );
231             free( tk->p_subpackets_timecode );
232         }
233
234         free( tk );
235     }
236
237     free( p_sys->psz_title );
238     free( p_sys->psz_artist );
239     free( p_sys->psz_copyright );
240     free( p_sys->psz_description );
241     free( p_sys->p_index );
242
243     if( p_sys->i_track > 0 ) free( p_sys->track );
244     free( p_sys );
245 }
246
247
248 /*****************************************************************************
249  * Demux:
250  *****************************************************************************/
251 static int Demux( demux_t *p_demux )
252 {
253     demux_sys_t *p_sys = p_demux->p_sys;
254     uint8_t     header[18];
255     int         i_size, i_id, i_flags, i;
256     int64_t     i_pts;
257     real_track_t *tk = NULL;
258     bool  b_selected;
259
260     if( p_sys->i_data_packets >= p_sys->i_data_packets_count &&
261         p_sys->i_data_packets_count )
262     {
263         if( stream_Read( p_demux->s, header, 18 ) < 18 )
264         {
265             return 0;
266         }
267         if( strncmp( (char *)header, "DATA", 4 ) )
268         {
269             return 0;
270         }
271         p_sys->i_data_offset = stream_Tell( p_demux->s ) - 18;
272         p_sys->i_data_size   = GetDWBE( &header[4] );
273         p_sys->i_data_packets_count = GetDWBE( &header[10] );
274         p_sys->i_data_packets = 0;
275         p_sys->i_data_offset_next = GetDWBE( &header[14] );
276
277         msg_Dbg( p_demux, "entering new DATA packets=%d next=%u",
278                  p_sys->i_data_packets_count,
279                  (uint32_t)p_sys->i_data_offset_next );
280     }
281
282     if( stream_Read( p_demux->s, header, 12 ) < 12 ) return 0;
283
284     i_size = GetWBE( &header[2] ) - 12;
285     i_id   = GetWBE( &header[4] );
286     i_pts  = 1000 * GetDWBE( &header[6] );
287     i_pts += 1000; /* Avoid 0 pts */
288     i_flags= header[11]; /* flags 0x02 -> keyframe */
289
290     msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u",
291              p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) );
292
293     p_sys->i_data_packets++;
294
295     stream_Read( p_demux->s, p_sys->buffer, i_size );
296
297     for( i = 0; i < p_sys->i_track; i++ )
298     {
299         if( p_sys->track[i]->i_id == i_id ) tk = p_sys->track[i];
300     }
301
302     if( tk == NULL )
303     {
304         msg_Warn( p_demux, "unknown track id(0x%x)", i_id );
305         return 1;
306     }
307     es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b_selected );
308
309     if( tk->fmt.i_cat == VIDEO_ES && b_selected )
310     {
311         uint8_t *p = p_sys->buffer;
312
313         while( p < &p_sys->buffer[i_size - 2] )
314         {
315             uint8_t h = *p++;
316             int     i_len = 0;
317             int     i_copy;
318             int     i_subseq = 0;
319             int     i_seqnum = 0;
320             int     i_offset = 0;
321
322             if( (h&0xc0) == 0x40 )
323             {
324                 /* Short header */
325                 p++;
326                 i_len = &p_sys->buffer[i_size] - p;
327             }
328             else
329             {
330                 if( (h&0x40) == 0 )
331                 {
332                     i_subseq = (*p++)&0x7f;
333                 }
334                 i_len = (p[0] << 8)|p[1]; p += 2;
335                 if( (i_len&0xc000) == 0 )
336                 {
337                     i_len <<= 16;
338                     i_len |= (p[0] << 8)|p[1]; p += 2;
339                     i_len &= 0x3fffffff;
340                 }
341                 else
342                 {
343                     i_len &= 0x3fff;
344                 }
345
346                 i_offset = (p[0] << 8)|p[1]; p += 2;
347                 if( (i_offset&0xc000) == 0 )
348                 {
349                     i_offset <<= 16;
350                     i_offset |= (p[0] << 8)|p[1]; p += 2;
351                     i_offset &= 0x3fffffff;
352                 }
353                 else
354                 {
355                     i_offset &= 0x3fff;
356                 }
357                 i_seqnum = *p++;
358             }
359
360             i_copy = i_len - i_offset;
361             if( i_copy > &p_sys->buffer[i_size] - p )
362             {
363                 i_copy = &p_sys->buffer[i_size] - p;
364             }
365             else if( i_copy < 0 )
366             {
367                 break;
368             }
369
370             msg_Dbg( p_demux, "    - len=%d offset=%d size=%d subseq=%d seqnum=%d",
371                      i_len, i_offset, i_copy, i_subseq, i_seqnum );
372
373             if( (h&0xc0) == 0x80 )
374             {
375                 /* last fragment -> fixes */
376                 i_copy = i_offset;
377                 i_offset = i_len - i_copy;
378                 msg_Dbg( p_demux, "last fixing copy=%d offset=%d",
379                          i_copy, i_offset );
380             }
381
382             if( tk->p_frame &&
383                 ( tk->p_frame->i_dts != i_pts ||
384                   tk->i_frame != i_len ) )
385             {
386                 msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer );
387
388                 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
389
390                 tk->i_frame = 0;
391                 tk->p_frame = NULL;
392             }
393
394             if( (h&0xc0) != 0x80 && (h&0xc0) != 0x00 && !tk->p_frame )
395             {
396                 /* no fragment */
397                 i_len = i_copy;
398                 i_offset = 0;
399             }
400
401
402             if( tk->p_frame == NULL )
403             {
404                 msg_Dbg( p_demux, "new frame size=%d", i_len );
405                 tk->i_frame = i_len;
406                 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
407                 {
408                     return -1;
409                 }
410                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
411                 tk->p_frame->i_dts = i_pts;
412                 tk->p_frame->i_pts = i_pts;
413
414                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
415                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 0;      /* chunk counts */
416             }
417
418             if( i_offset < tk->i_frame)
419             {
420                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
421
422                 msg_Dbg( p_demux, "copying new buffer n=%d offset=%d copy=%d",
423                          i_ck, i_offset, i_copy );
424
425                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck*2 +0 ] = 1;
426                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck*2 +1 ] = i_offset;
427
428
429                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
430             }
431
432             p += i_copy;
433
434             if( (h&0xc0) != 0x80 )
435             {
436                 break;
437             }
438
439 #if 0
440             if( tk->p_frame )
441             {
442                 /* append data */
443                 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
444
445                 if( (h&0xc0) == 0x80 )
446                 {
447                     /* last fragment */
448                     i_copy = i_offset;
449                     i_offset = i_len - i_offset;
450
451                     ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
452                     memcpy( &tk->p_frame->p_buffer[i_offset+ 8], p, i_copy );
453                     p += i_copy;
454
455                     if( p_sys->i_pcr < tk->p_frame->i_dts )
456                     {
457                         p_sys->i_pcr = tk->p_frame->i_dts;
458                         es_out_Control( p_demux->out, ES_OUT_SET_PCR,
459                                         (int64_t)p_sys->i_pcr );
460                     }
461                     es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
462
463                     tk->i_frame = 0;
464                     tk->p_frame = NULL;
465
466                     continue;
467                 }
468
469                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
470                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
471                 break;
472             }
473
474             if( (h&0xc0) != 0x00 )
475             {
476                 block_t *p_frame;
477
478                 /* not fragmented */
479                 if( !( p_frame = block_New( p_demux, i_copy + 8 + 8 ) ) )
480                 {
481                     return -1;
482                 }
483                 p_frame->i_dts = i_pts;
484                 p_frame->i_pts = i_pts;
485
486                 ((uint32_t*)p_frame->p_buffer)[0] = i_copy;
487                 ((uint32_t*)p_frame->p_buffer)[1] = 1;
488                 ((uint32_t*)(p_frame->p_buffer+i_copy+8))[0] = 0;
489                 memcpy( &p_frame->p_buffer[8], p, i_copy );
490
491                 p += i_copy;
492
493                 if( p_sys->i_pcr < p_frame->i_dts )
494                 {
495                     p_sys->i_pcr = p_frame->i_dts;
496                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
497                                     (int64_t)p_sys->i_pcr );
498                 }
499                 es_out_Send( p_demux->out, tk->p_es, p_frame );
500             }
501             else
502             {
503                 /* First fragment */
504                 tk->i_frame = i_len;
505                 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
506                 {
507                     return -1;
508                 }
509                 memset( &tk->p_frame->p_buffer[8], 0, i_len );
510                 tk->p_frame->i_dts = i_pts;
511                 tk->p_frame->i_pts = i_pts;
512
513                 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;  /* len */
514                 ((uint32_t*)tk->p_frame->p_buffer)[1] = 1;      /* chunk counts */
515                 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[0] = i_offset;
516                 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
517
518                 break;
519             }
520 #endif
521         }
522     }
523     else if( tk->fmt.i_cat == AUDIO_ES && b_selected )
524     {
525         if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
526             tk->fmt.i_codec == VLC_FOURCC( 'a', 't', 'r', 'c') ||
527             tk->fmt.i_codec == VLC_FOURCC( 's', 'i', 'p', 'r') ||
528             tk->fmt.i_codec == VLC_FOURCC( '2', '8', '_', '8') )
529         {
530             uint8_t *p_buf = p_sys->buffer;
531             int y = tk->i_subpacket / ( tk->i_frame_size /tk->i_subpacket_size);
532             int i_index, i;
533
534             /* Sanity check */
535             if( i_flags & 2 || ( p_sys->b_seek ) )
536             {
537                 y = tk->i_subpacket = 0;
538                 tk->i_out_subpacket = 0;
539                 p_sys->b_seek = 0;
540             }
541
542             if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
543                 tk->fmt.i_codec == VLC_FOURCC( 'a', 't', 'r', 'c' ))
544             {
545                 int num = tk->i_frame_size / tk->i_subpacket_size;
546                 for( i = 0; i <  num; i++ )
547                 {
548                     block_t *p_block = block_New( p_demux, tk->i_subpacket_size );
549                     memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size );
550                     p_buf += tk->i_subpacket_size;
551
552                     i_index = tk->i_subpacket_h * i +
553                         ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1);
554
555                     if ( tk->p_subpackets[i_index]  != NULL )
556                     {
557                         msg_Dbg(p_demux, "p_subpackets[ %d ] not null!",  i_index );
558                         free( tk->p_subpackets[i_index] );
559                     }
560
561                     tk->p_subpackets[i_index] = p_block;
562                     tk->i_subpacket++;
563                     p_block->i_dts = p_block->i_pts = 0;
564                 }
565                 tk->p_subpackets_timecode[tk->i_subpacket - num] = i_pts;
566             }
567
568             if( tk->fmt.i_codec == VLC_FOURCC( '2', '8', '_', '8' ) ||
569                 tk->fmt.i_codec == VLC_FOURCC( 's', 'i', 'p', 'r' ) )
570             for( i = 0; i < tk->i_subpacket_h / 2; i++ )
571             {
572                 block_t *p_block = block_New( p_demux, tk->i_coded_frame_size);
573                 memcpy( p_block->p_buffer, p_buf, tk->i_coded_frame_size );
574                 p_buf += tk->i_coded_frame_size;
575
576                 i_index = (i * 2 * tk->i_frame_size) /
577                     tk->i_coded_frame_size + y;
578
579                 p_block->i_dts = p_block->i_pts = i_pts;
580                 tk->p_subpackets[i_index] = p_block;
581                 tk->i_subpacket++;
582             }
583
584             while( tk->i_out_subpacket != tk->i_subpackets &&
585                    tk->p_subpackets[tk->i_out_subpacket] )
586             {
587                 /* Set the PCR */
588 #if 0
589                 if (tk->i_out_subpacket == 0)
590                 {
591                     p_sys->i_pcr = tk->p_subpackets[tk->i_out_subpacket]->i_dts;
592                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
593                             (int64_t)p_sys->i_pcr );
594                 }
595
596                 block_t *p_block = tk->p_subpackets[tk->i_out_subpacket];
597                 tk->p_subpackets[tk->i_out_subpacket] = 0;
598
599                 if( tk->i_out_subpacket ) p_block->i_dts = p_block->i_pts = 0;
600 #endif
601
602                 block_t *p_block = tk->p_subpackets[tk->i_out_subpacket];
603                 tk->p_subpackets[tk->i_out_subpacket] = 0;
604                 if ( tk->p_subpackets_timecode[tk->i_out_subpacket]  )
605                 {
606                     p_block->i_dts = p_block->i_pts =
607                         tk->p_subpackets_timecode[tk->i_out_subpacket];
608                     tk->p_subpackets_timecode[tk->i_out_subpacket] = 0;
609
610                     p_sys->i_pcr = p_block->i_dts;
611                     es_out_Control( p_demux->out, ES_OUT_SET_PCR,
612                             (int64_t)p_sys->i_pcr );
613                 }
614                 es_out_Send( p_demux->out, tk->p_es, p_block );
615
616                 tk->i_out_subpacket++;
617             }
618
619             if( tk->i_subpacket == tk->i_subpackets &&
620                 tk->i_out_subpacket != tk->i_subpackets )
621             {
622                 msg_Warn( p_demux, "i_subpacket != i_out_subpacket, "
623                           "this shouldn't happen" );
624             }
625
626             if( tk->i_subpacket == tk->i_subpackets )
627             {
628                 tk->i_subpacket = 0;
629                 tk->i_out_subpacket = 0;
630             }
631         }
632         else
633         {
634             /* Set PCR */
635             if( p_sys->i_pcr < i_pts )
636             {
637                 p_sys->i_pcr = i_pts;
638                 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
639                         (int64_t)p_sys->i_pcr );
640             }
641
642             if( tk->fmt.i_codec == VLC_FOURCC( 'm','p','4','a' ) )
643             {
644                 int     i_sub = (p_sys->buffer[1] >> 4)&0x0f;
645                 uint8_t *p_sub = &p_sys->buffer[2+2*i_sub];
646
647                 int i;
648                 for( i = 0; i < i_sub; i++ )
649                 {
650                     int i_sub_size = GetWBE( &p_sys->buffer[2+i*2]);
651                     block_t *p_block = block_New( p_demux, i_sub_size );
652                     if( p_block )
653                     {
654                         memcpy( p_block->p_buffer, p_sub, i_sub_size );
655                         p_sub += i_sub_size;
656
657                         p_block->i_dts =
658                             p_block->i_pts = ( i == 0 ? i_pts : 0 );
659
660                         es_out_Send( p_demux->out, tk->p_es, p_block );
661                     }
662                 }
663             }
664             else
665             {
666                 block_t *p_block = block_New( p_demux, i_size );
667
668                 if( tk->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', ' ' ) )
669                 {
670                     uint8_t *src = p_sys->buffer;
671                     uint8_t *dst = p_block->p_buffer;
672
673                     /* byte swap data */
674                     while( dst < &p_block->p_buffer[i_size- 1])
675                     {
676                         *dst++ = src[1];
677                         *dst++ = src[0];
678
679                         src += 2;
680                     }
681                 }
682                 else
683                 {
684                     memcpy( p_block->p_buffer, p_sys->buffer, i_size );
685                 }
686                 p_block->i_dts = p_block->i_pts = i_pts;
687                 es_out_Send( p_demux->out, tk->p_es, p_block );
688             }
689         }
690     }
691
692
693     return 1;
694 }
695
696 /*****************************************************************************
697  * Control:
698  *****************************************************************************/
699 static int Control( demux_t *p_demux, int i_query, va_list args )
700 {
701     demux_sys_t *p_sys = p_demux->p_sys;
702     double f, *pf;
703     int64_t i64;
704     rm_index_t * p_index;
705     int64_t *pi64;
706
707     switch( i_query )
708     {
709         case DEMUX_GET_POSITION:
710             pf = (double*) va_arg( args, double* );
711
712             if( p_sys->i_our_duration > 0 )
713             {
714                 *pf = (double)p_sys->i_pcr / 1000.0 / p_sys->i_our_duration;
715                 return VLC_SUCCESS;
716             }
717
718             /* read stream size maybe failed in rtsp streaming, 
719                so use duration to determin the position at first  */
720             i64 = stream_Size( p_demux->s );
721             if( i64 > 0 )
722             {
723                 *pf = (double)1.0*stream_Tell( p_demux->s ) / (double)i64;
724             }
725             else
726             {
727                 *pf = 0.0;
728             }
729             return VLC_SUCCESS;
730
731         case DEMUX_GET_TIME:
732             pi64 = (int64_t*)va_arg( args, int64_t * );
733
734             if( p_sys->i_our_duration > 0 )
735             {
736                 *pi64 = p_sys->i_pcr;
737                 return VLC_SUCCESS;
738             }
739
740             /* same as GET_POSTION */
741             i64 = stream_Size( p_demux->s );
742             if( p_sys->i_our_duration > 0 && i64 > 0 )
743             {
744                 *pi64 = (int64_t)( 1000.0 * p_sys->i_our_duration * stream_Tell( p_demux->s ) / i64 );
745                 return VLC_SUCCESS;
746             }
747
748             *pi64 = 0;
749             return VLC_EGENERIC;
750
751         case DEMUX_SET_POSITION:
752             f = (double) va_arg( args, double );
753             i64 = (int64_t) ( stream_Size( p_demux->s ) * f );
754
755             if ( p_sys->i_index_offset == 0 && i64 != 0 )
756             {
757                 msg_Err(p_demux,"Seek No Index Real File failed!" );
758                 return VLC_EGENERIC; // no index!
759             }
760             if ( i64 == 0 )
761             {
762                 /* it is a rtsp stream , it is specials in access/rtsp/... */
763                 msg_Dbg(p_demux, "Seek in real rtsp stream!");
764                 p_sys->i_pcr = (int64_t)1000 * ( p_sys->i_our_duration * f  );
765
766                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr );
767                 p_sys->b_seek = 1;
768
769                 return stream_Seek( p_demux->s, p_sys->i_pcr );
770             }
771
772             if ( p_sys->i_index_offset > 0 )
773             {
774                 p_index = p_sys->p_index;
775                 while( p_index->file_offset !=0 )
776                 {
777                     if ( p_index->file_offset > i64 )
778                     {
779                         msg_Dbg( p_demux, "Seek Real find! %d %d %d",
780                                  p_index->time_offset, p_index->file_offset,
781                                  (uint32_t) i64 );
782                         if ( p_index != p_sys->p_index ) p_index --;
783                         i64 = p_index->file_offset;
784                         break;
785                     }
786                     p_index++;
787                 }
788
789                 p_sys->i_pcr = 1000 * (int64_t) p_index->time_offset;
790
791                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr );
792
793                 return stream_Seek( p_demux->s, i64 );
794             }
795         case DEMUX_SET_TIME:
796             i64 = (int64_t) va_arg( args, int64_t ) / 1000;
797
798             p_index = p_sys->p_index;
799             while( p_index->file_offset !=0 )
800             {
801                 if ( p_index->time_offset > i64 )
802                 {
803                     if ( p_index != p_sys->p_index )
804                         p_index --;
805                     i64 = p_index->file_offset;
806                     break;
807                 }
808                 p_index++;
809             }
810
811             p_sys->i_pcr = 1000 * (int64_t) p_index->time_offset;
812             es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr );
813
814             return stream_Seek( p_demux->s, i64 );
815
816         case DEMUX_GET_LENGTH:
817             pi64 = (int64_t*)va_arg( args, int64_t * );
818  
819             /* the commented following lines are fen's implementation, which doesn't seem to
820              * work for one reason or another -- FK */
821             /*if( p_sys->i_mux_rate > 0 )
822             {
823                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
824                 return VLC_SUCCESS;
825             }*/
826             if( p_sys->i_our_duration > 0 )
827             {
828                 /* our stored duration is in ms, so... */
829                 *pi64 = (int64_t)1000 * p_sys->i_our_duration;
830  
831                 return VLC_SUCCESS;
832             }
833             *pi64 = 0;
834             return VLC_EGENERIC;
835
836         case DEMUX_GET_META:
837         {
838             vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
839
840             /* the core will crash if we provide NULL strings, so check
841              * every string first */
842             if( p_sys->psz_title )
843                 vlc_meta_SetTitle( p_meta, p_sys->psz_title );
844             if( p_sys->psz_artist )
845                 vlc_meta_SetArtist( p_meta, p_sys->psz_artist );
846             if( p_sys->psz_copyright )
847                 vlc_meta_SetCopyright( p_meta, p_sys->psz_copyright );
848             if( p_sys->psz_description )
849                 vlc_meta_SetDescription( p_meta, p_sys->psz_description );
850             return VLC_SUCCESS;
851         }
852
853         case DEMUX_GET_FPS:
854         default:
855             return VLC_EGENERIC;
856     }
857     return VLC_EGENERIC;
858 }
859
860 /*****************************************************************************
861  * ReadRealIndex:
862  *****************************************************************************/
863
864 static void ReadRealIndex( demux_t *p_demux )
865 {
866     demux_sys_t *p_sys = p_demux->p_sys;
867     uint8_t       buffer[100];
868     uint32_t      i_id;
869     uint32_t      i_size;
870     int           i_version;
871     unsigned int  i;
872
873     uint32_t      i_index_count;
874
875     if ( p_sys->i_index_offset == 0 )
876         return;
877
878     stream_Seek( p_demux->s, p_sys->i_index_offset );
879
880     if ( stream_Read( p_demux->s, buffer, 20 ) < 20 )
881         return ;
882
883     i_id = VLC_FOURCC( buffer[0], buffer[1], buffer[2], buffer[3] );
884     i_size      = GetDWBE( &buffer[4] );
885     i_version   = GetWBE( &buffer[8] );
886
887     msg_Dbg( p_demux, "Real index %4.4s size=%d version=%d",
888                  (char*)&i_id, i_size, i_version );
889
890     if( (i_size < 20) && (i_id != VLC_FOURCC('I','N','D','X')) )
891         return;
892
893     i_index_count = GetDWBE( &buffer[10] );
894
895     msg_Dbg( p_demux, "Real Index : num : %d ", i_index_count );
896
897     if( i_index_count == 0 )
898         return;
899
900     if( GetDWBE( &buffer[16] ) > 0 )
901         msg_Dbg( p_demux, "Real Index: Does next index exist? %d ",
902                         GetDWBE( &buffer[16] )  );
903
904     p_sys->p_index = 
905             (rm_index_t *)malloc( sizeof( rm_index_t ) * (i_index_count+1) );
906     if( p_sys->p_index == NULL )
907     {
908         msg_Err( p_demux, "Memory allocation error" ); 
909         return;
910     }
911
912     memset( p_sys->p_index, 0, sizeof(rm_index_t) * (i_index_count+1) );
913
914     for( i=0; i<i_index_count; i++ )
915     {
916         if( stream_Read( p_demux->s, buffer, 14 ) < 14 )
917             return ;
918
919         if( GetWBE( &buffer[0] ) != 0 )
920         {
921             msg_Dbg( p_demux, "Real Index: invaild version of index entry %d ",
922                               GetWBE( &buffer[0] ) );
923             return;
924         }
925
926         p_sys->p_index[i].time_offset = GetDWBE( &buffer[2] );
927         p_sys->p_index[i].file_offset = GetDWBE( &buffer[6] );
928         p_sys->p_index[i].frame_index = GetDWBE( &buffer[10] );
929         msg_Dbg( p_demux, "Real Index: time %d file %d frame %d ",
930                         p_sys->p_index[i].time_offset,
931                         p_sys->p_index[i].file_offset,
932                         p_sys->p_index[i].frame_index );
933
934     }
935 }
936
937 /*****************************************************************************
938  * HeaderRead:
939  *****************************************************************************/
940 static int HeaderRead( demux_t *p_demux )
941 {
942     demux_sys_t *p_sys = p_demux->p_sys;
943     uint8_t header[100];    /* FIXME */
944
945     uint32_t    i_id;
946     uint32_t    i_size;
947     int64_t     i_skip;
948     int         i_version;
949     p_sys->p_meta = vlc_meta_New();
950
951     for( ;; )
952     {
953         /* Read the header */
954         if( stream_Read( p_demux->s, header, 10 ) < 10 )
955         {
956             return VLC_EGENERIC;
957         }
958         i_id        = VLC_FOURCC( header[0], header[1], header[2], header[3] );
959         i_size      = GetDWBE( &header[4] );
960         i_version   = GetWBE( &header[8] );
961
962         msg_Dbg( p_demux, "object %4.4s size=%d version=%d",
963                  (char*)&i_id, i_size, i_version );
964
965         if( i_size < 10 && i_id != VLC_FOURCC('D','A','T','A') )
966         {
967             msg_Dbg( p_demux, "invalid size for object %4.4s", (char*)&i_id );
968             return VLC_EGENERIC;
969         }
970         i_skip = i_size - 10;
971
972         if( i_id == VLC_FOURCC('.','R','M','F') )
973         {
974             if( stream_Read( p_demux->s, header, 8 ) < 8 ) return VLC_EGENERIC;
975             msg_Dbg( p_demux, "    - file version=0x%x num headers=%d",
976                      GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
977
978             i_skip -= 8;
979         }
980         else if( i_id == VLC_FOURCC('P','R','O','P') )
981         {
982             int i_flags;
983
984             if( stream_Read(p_demux->s, header, 40) < 40 ) return VLC_EGENERIC;
985
986             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d",
987                      GetDWBE(&header[0]), GetDWBE(&header[4]) );
988             msg_Dbg( p_demux, "    - max packet size=%d avg bitrate=%d",
989                      GetDWBE(&header[8]), GetDWBE(&header[12]) );
990             msg_Dbg( p_demux, "    - packets count=%d", GetDWBE(&header[16]) );
991             msg_Dbg( p_demux, "    - duration=%d ms", GetDWBE(&header[20]) );
992             msg_Dbg( p_demux, "    - preroll=%d ms", GetDWBE(&header[24]) );
993             msg_Dbg( p_demux, "    - index offset=%d", GetDWBE(&header[28]) );
994             msg_Dbg( p_demux, "    - data offset=%d", GetDWBE(&header[32]) );
995             msg_Dbg( p_demux, "    - num streams=%d", GetWBE(&header[36]) );
996  
997             /* set the duration for export in control */
998             p_sys->i_our_duration = (int)GetDWBE(&header[20]);
999  
1000             p_sys->i_index_offset = GetDWBE(&header[28]);
1001
1002             i_flags = GetWBE(&header[38]);
1003             msg_Dbg( p_demux, "    - flags=0x%x %s%s%s",
1004                      i_flags,
1005                      i_flags&0x0001 ? "PN_SAVE_ENABLED " : "",
1006                      i_flags&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
1007                      i_flags&0x0004 ? "PN_LIVE_BROADCAST" : "" );
1008             i_skip -= 40;
1009         }
1010         else if( i_id == VLC_FOURCC('C','O','N','T') )
1011         {
1012             int i_len;
1013             char *psz;
1014  
1015             /* FIXME FIXME: should convert from whatever the character
1016              * encoding of the input meta data is to UTF-8. */
1017
1018             stream_Read( p_demux->s, header, 2 );
1019             if( ( i_len = GetWBE( header ) ) > 0 )
1020             {
1021                 psz = malloc( i_len + 1 );
1022                 stream_Read( p_demux->s, psz, i_len );
1023                 psz[i_len] = '\0';
1024
1025                 EnsureUTF8( psz );
1026                 msg_Dbg( p_demux, "    - title=`%s'", psz );
1027                 p_sys->psz_title = psz;
1028                 i_skip -= i_len;
1029             }
1030             i_skip -= 2;
1031
1032             stream_Read( p_demux->s, header, 2 );
1033             if( ( i_len = GetWBE( header ) ) > 0 )
1034             {
1035                 psz = malloc( i_len + 1 );
1036                 stream_Read( p_demux->s, psz, i_len );
1037                 psz[i_len] = '\0';
1038
1039                 EnsureUTF8( psz );
1040                 msg_Dbg( p_demux, "    - author=`%s'", psz );
1041                 p_sys->psz_artist = psz;
1042                 i_skip -= i_len;
1043             }
1044             i_skip -= 2;
1045
1046             stream_Read( p_demux->s, header, 2 );
1047             if( ( i_len = GetWBE( header ) ) > 0 )
1048             {
1049                 psz = malloc( i_len + 1 );
1050                 stream_Read( p_demux->s, psz, i_len );
1051                 psz[i_len] = '\0';
1052
1053                 EnsureUTF8( psz );
1054                 msg_Dbg( p_demux, "    - copyright=`%s'", psz );
1055                 p_sys->psz_copyright = psz;
1056                 i_skip -= i_len;
1057             }
1058             i_skip -= 2;
1059
1060             stream_Read( p_demux->s, header, 2 );
1061             if( ( i_len = GetWBE( header ) ) > 0 )
1062             {
1063                 psz = malloc( i_len + 1 );
1064                 stream_Read( p_demux->s, psz, i_len );
1065                 psz[i_len] = '\0';
1066
1067                 EnsureUTF8( psz );
1068                 msg_Dbg( p_demux, "    - comment=`%s'", psz );
1069                 p_sys->psz_description = psz;
1070                 i_skip -= i_len;
1071             }
1072             i_skip -= 2;
1073         }
1074         else if( i_id == VLC_FOURCC('M','D','P','R') )
1075         {
1076             /* Media properties header */
1077             int  i_num;
1078             int  i_len;
1079             char *psz;
1080
1081             if( stream_Read(p_demux->s, header, 30) < 30 ) return VLC_EGENERIC;
1082             i_num = GetWBE( header );
1083             msg_Dbg( p_demux, "    - id=0x%x", i_num );
1084             msg_Dbg( p_demux, "    - max bitrate=%d avg bitrate=%d",
1085                      GetDWBE(&header[2]), GetDWBE(&header[6]) );
1086             msg_Dbg( p_demux, "    - max packet size=%d avg packet size=%d",
1087                      GetDWBE(&header[10]), GetDWBE(&header[14]) );
1088             msg_Dbg( p_demux, "    - start time=%d", GetDWBE(&header[18]) );
1089             msg_Dbg( p_demux, "    - preroll=%d", GetDWBE(&header[22]) );
1090             msg_Dbg( p_demux, "    - duration=%d", GetDWBE(&header[26]) );
1091  
1092             i_skip -= 30;
1093
1094             stream_Read( p_demux->s, header, 1 );
1095             if( ( i_len = header[0] ) > 0 )
1096             {
1097                 psz = malloc( i_len + 1 );
1098                 stream_Read( p_demux->s, psz, i_len );
1099                 psz[i_len] = '\0';
1100
1101                 msg_Dbg( p_demux, "    - name=`%s'", psz );
1102                 free( psz );
1103                 i_skip -= i_len;
1104             }
1105             i_skip--;
1106
1107             stream_Read( p_demux->s, header, 1 );
1108             if( ( i_len = header[0] ) > 0 )
1109             {
1110                 psz = malloc( i_len + 1 );
1111                 stream_Read( p_demux->s, psz, i_len );
1112                 psz[i_len] = '\0';
1113
1114                 msg_Dbg( p_demux, "    - mime=`%s'", psz );
1115                 free( psz );
1116                 i_skip -= i_len;
1117             }
1118             i_skip--;
1119
1120             stream_Read( p_demux->s, header, 4 );
1121             if( ( i_len = GetDWBE( header ) ) > 0 )
1122             {
1123                 ReadCodecSpecificData( p_demux, i_len, i_num );
1124                 stream_Read( p_demux->s, NULL, i_len );
1125
1126                 i_skip -= i_len;
1127             }
1128             i_skip -= 4;
1129         }
1130         else if( i_id == VLC_FOURCC('D','A','T','A') )
1131         {
1132             stream_Read( p_demux->s, header, 8 );
1133
1134             p_sys->i_data_offset    = stream_Tell( p_demux->s ) - 10;
1135             p_sys->i_data_size      = i_size;
1136             p_sys->i_data_packets_count = GetDWBE( header );
1137             p_sys->i_data_packets   = 0;
1138             p_sys->i_data_offset_next = GetDWBE( &header[4] );
1139
1140             msg_Dbg( p_demux, "    - packets count=%d next=%u",
1141                      p_sys->i_data_packets_count,
1142                      (uint32_t)p_sys->i_data_offset_next );
1143
1144             /* we have finished the header */
1145             break;
1146         }
1147         else
1148         {
1149             /* unknow header */
1150             msg_Dbg( p_demux, "unknown chunk" );
1151         }
1152
1153         if( i_skip < 0 ) return VLC_EGENERIC;
1154         stream_Read( p_demux->s, NULL, i_skip );
1155     }
1156
1157     /* TODO read index if possible */
1158
1159     if ( p_sys->i_index_offset > 0 )
1160     {
1161         int64_t pos;
1162         pos = stream_Tell( p_demux->s );
1163         ReadRealIndex( p_demux );
1164         stream_Seek( p_demux->s, pos );
1165     }
1166
1167     return VLC_SUCCESS;
1168 }
1169
1170 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num )
1171 {
1172     demux_sys_t *p_sys = p_demux->p_sys;
1173     es_format_t fmt;
1174     real_track_t *tk;
1175     const uint8_t *p_peek;
1176
1177     msg_Dbg( p_demux, "    - specific data len=%d", i_len );
1178     if( stream_Peek(p_demux->s, &p_peek, i_len) < i_len ) return VLC_EGENERIC;
1179
1180     if( ( i_len >= 8 ) && !memcmp( &p_peek[4], "VIDO", 4 ) )
1181     {
1182         es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( p_peek[8], p_peek[9],
1183                         p_peek[10], p_peek[11] ) );
1184         fmt.video.i_width = GetWBE( &p_peek[12] );
1185         fmt.video.i_height= GetWBE( &p_peek[14] );
1186
1187         fmt.i_extra = 8;
1188         fmt.p_extra = malloc( 8 );
1189         ((uint32_t*)fmt.p_extra)[0] = GetDWBE( &p_peek[26] );
1190         ((uint32_t*)fmt.p_extra)[1] = GetDWBE( &p_peek[30] );
1191
1192         msg_Dbg( p_demux, "    - video 0x%08x 0x%08x",
1193                  ((uint32_t*)fmt.p_extra)[0], ((uint32_t*)fmt.p_extra)[1] );
1194
1195         if( GetDWBE( &p_peek[30] ) == 0x10003000 ||
1196             GetDWBE( &p_peek[30] ) == 0x10003001 )
1197         {
1198             fmt.i_codec = VLC_FOURCC( 'R','V','1','3' );
1199         }
1200         else if( GetDWBE( &p_peek[30] ) == 0x20001000 ||
1201                  GetDWBE( &p_peek[30] ) == 0x20100001 ||
1202                  GetDWBE( &p_peek[30] ) == 0x20200002 )
1203         {
1204             fmt.i_codec = VLC_FOURCC( 'R','V','2','0' );
1205         }
1206         else if( GetDWBE( &p_peek[30] ) == 0x30202002 )
1207         {
1208             fmt.i_codec = VLC_FOURCC( 'R','V','3','0' );
1209         }
1210         else if( GetDWBE( &p_peek[30] ) == 0x40000000 )
1211         {
1212             fmt.i_codec = VLC_FOURCC( 'R','V','4','0' );
1213         }
1214
1215         msg_Dbg( p_demux, "    - video %4.4s %dx%d",
1216                  (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
1217
1218         tk = malloc( sizeof( real_track_t ) );
1219         tk->i_out_subpacket = 0;
1220         tk->i_subpacket = 0;
1221         tk->i_subpackets = 0;
1222         tk->p_subpackets = NULL;
1223         tk->p_subpackets_timecode = NULL;
1224         tk->i_id = i_num;
1225         tk->fmt = fmt;
1226         tk->i_frame = 0;
1227         tk->p_frame = NULL;
1228         tk->p_es = es_out_Add( p_demux->out, &fmt );
1229
1230         TAB_APPEND( p_sys->i_track, p_sys->track, tk );
1231     }
1232     else if( !strncmp( (char *)p_peek, ".ra\xfd", 4 ) )
1233     {
1234         int i_header_size = 0;
1235         int i_flavor = 0;
1236         int i_coded_frame_size = 0;
1237         int i_subpacket_h = 0;
1238         int i_frame_size = 0;
1239         int i_subpacket_size = 0;
1240         char p_genr[4];
1241         int i_version = GetWBE( &p_peek[4] );   /* [0..3] = '.','r','a',0xfd */
1242         msg_Dbg( p_demux, "    - audio version=%d", i_version );
1243
1244         p_peek += 6;                                          /* 4 + version */
1245         es_format_Init( &fmt, AUDIO_ES, 0 );
1246
1247         if( i_version == 3 )
1248         {
1249             int i_len;
1250             char *psz;
1251
1252             i_header_size = GetWBE( p_peek ); p_peek += 2;  /* Size from now */
1253             p_peek += 10;                                         /* Unknown */
1254
1255             p_peek += 4;                                        /* Data Size */
1256
1257             /* Title */
1258             i_len = *p_peek ; p_peek++;
1259             if( i_len > 0 )
1260             {
1261                 psz = malloc( i_len + 1 );
1262                 memcpy( psz, p_peek, i_len );
1263                 psz[i_len] = '\0';
1264
1265                 EnsureUTF8( psz );
1266                 msg_Dbg( p_demux, "    - title=`%s'", psz );
1267                 p_sys->psz_title = psz;
1268             }
1269             p_peek += i_len;
1270
1271             /* Authors */
1272             i_len = *p_peek ; p_peek++;
1273             if( i_len > 0 )
1274             {
1275                 psz = malloc( i_len + 1 );
1276                 memcpy( psz, p_peek, i_len );
1277                 psz[i_len] = '\0';
1278
1279                 EnsureUTF8( psz );
1280                 msg_Dbg( p_demux, "    - artist=`%s'", psz );
1281                 p_sys->psz_artist = psz;
1282             }
1283             p_peek += i_len;
1284
1285             /* Copyright */
1286             i_len = *p_peek ; p_peek++;
1287             if( i_len > 0 )
1288             {
1289                 psz = malloc( i_len + 1 );
1290                 memcpy( psz, p_peek, i_len );
1291                 psz[i_len] = '\0';
1292
1293                 EnsureUTF8( psz );
1294                 msg_Dbg( p_demux, "    - Copyright=`%s'", psz );
1295                 p_sys->psz_copyright = psz;
1296             }
1297             p_peek += i_len;
1298
1299             /* Comment */
1300             i_len = *p_peek ; p_peek++;
1301             if( i_len > 0 )
1302             {
1303                 psz = malloc( i_len + 1 );
1304                 memcpy( psz, p_peek, i_len );
1305                 psz[i_len] = '\0';
1306
1307                 EnsureUTF8( psz );
1308                 msg_Dbg( p_demux, "    - Comment=`%s'", psz );
1309                 p_sys->psz_description = psz;
1310             }
1311             /* This might be unusefull */
1312             p_peek += i_len;
1313
1314             p_peek ++;                                           /* Unknown */
1315             p_peek ++;                                 /* FourCC length = 4 */
1316             memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4;
1317             /* Up to here :) */
1318
1319             fmt.audio.i_channels = 1;      /* This is always the case in rm3 */
1320             fmt.audio.i_rate = 8000;
1321
1322             msg_Dbg( p_demux, "    - audio codec=%4.4s channels=%d rate=%dHz",
1323                  (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate );
1324         }
1325         else /* RMF version 4/5 */
1326         {
1327             p_peek += 2;                                           /* 00 00 */
1328             p_peek += 4;                                    /* .ra4 or .ra5 */
1329             p_peek += 4;                                       /* data size */
1330             p_peek += 2;                                /* version (4 or 5) */
1331             i_header_size = GetDWBE( p_peek ); p_peek += 4;   /* header size */
1332             i_flavor = GetWBE( p_peek ); p_peek += 2;        /* codec flavor */
1333             i_coded_frame_size = GetDWBE( p_peek ); p_peek += 4; /* coded frame size*/
1334             p_peek += 4;                                               /* ?? */
1335             p_peek += 4;                                               /* ?? */
1336             p_peek += 4;                                               /* ?? */
1337             i_subpacket_h = GetWBE( p_peek ); p_peek += 2;              /* 1 */
1338             i_frame_size = GetWBE( p_peek ); p_peek += 2;      /* frame size */
1339             i_subpacket_size = GetWBE( p_peek ); p_peek += 2;  /* subpacket_size */
1340             if( !i_subpacket_size || !i_frame_size || !i_coded_frame_size )
1341                  return VLC_EGENERIC;
1342             p_peek += 2;                                               /* ?? */
1343
1344             if( i_version == 5 ) p_peek += 6;                 /* 0, srate, 0 */
1345
1346             fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2; /* Sample Rate */
1347             p_peek += 2;                                               /* ?? */
1348             fmt.audio.i_bitspersample = GetWBE( p_peek ); p_peek += 2;/* Sure?*/
1349             fmt.audio.i_channels = GetWBE( p_peek ); p_peek += 2; /* Channels */
1350             fmt.audio.i_blockalign = i_frame_size;
1351
1352             if( i_version == 5 )
1353             {
1354                 memcpy( (char *)p_genr, p_peek, 4 ); p_peek += 4;    /* genr */
1355                 memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4;
1356             }
1357             else
1358             {
1359                 p_peek += p_peek[0] + 1;                          /* descr 1 */
1360                 memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 );    /* descr 2 */
1361                 p_peek += p_peek[0] + 1;
1362             }
1363
1364             msg_Dbg( p_demux, "    - audio codec=%4.4s channels=%d rate=%dHz",
1365                  (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate );
1366
1367             p_peek += 3;                                               /* ?? */
1368             if( i_version == 5 ) p_peek++;
1369             /* Extra Data then: DWord + byte[] */
1370             fmt.i_extra = GetDWBE( p_peek ); p_peek += 4;
1371         }
1372
1373         switch( fmt.i_codec )
1374         {
1375         case VLC_FOURCC('1','4','_','4'):
1376             /* fmt.audio.i_blockalign = 0x14 */
1377             break;
1378         case VLC_FOURCC('l','p','c','J'):
1379             /* fmt.audio.i_blockalign = 0x14 */
1380             fmt.i_codec = VLC_FOURCC( '1','4','_','4' );
1381             break;
1382
1383         case VLC_FOURCC('2','8','_','8'):
1384             fmt.i_extra = 0;
1385             fmt.audio.i_blockalign = i_coded_frame_size;
1386             break;
1387
1388         case VLC_FOURCC( 'd','n','e','t' ):
1389             fmt.i_codec = VLC_FOURCC( 'a','5','2',' ' );
1390             break;
1391
1392         case VLC_FOURCC( 'r','a','a','c' ):
1393         case VLC_FOURCC( 'r','a','c','p' ):
1394             fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );
1395
1396             if( fmt.i_extra > 0 ) { fmt.i_extra--; p_peek++; }
1397             if( fmt.i_extra > 0 )
1398             {
1399                 fmt.p_extra = malloc( fmt.i_extra );
1400                 if( fmt.p_extra == NULL )
1401                 {
1402                     msg_Err( p_demux, "Error in the extra data" );
1403                     return VLC_EGENERIC;
1404                 }
1405                 memcpy( fmt.p_extra, p_peek, fmt.i_extra );
1406             }
1407             break;
1408
1409         case VLC_FOURCC('s','i','p','r'):
1410             fmt.audio.i_flavor = i_flavor;
1411         case VLC_FOURCC('c','o','o','k'):
1412         case VLC_FOURCC('a','t','r','c'):
1413             if( !memcmp( p_genr, "genr", 4 ) )
1414                 fmt.audio.i_blockalign = i_subpacket_size;
1415             else
1416                 fmt.audio.i_blockalign = i_coded_frame_size;
1417
1418             if( fmt.i_extra > 0 )
1419             {
1420                 fmt.p_extra = malloc( fmt.i_extra );
1421                 if( fmt.p_extra == NULL )
1422                 {
1423                     msg_Err( p_demux, "Error in the extra data" );
1424                     return VLC_EGENERIC;
1425                 }
1426                 memcpy( fmt.p_extra, p_peek, fmt.i_extra );
1427             }
1428             break;
1429
1430         case VLC_FOURCC('r','a','l','f'):
1431             msg_Dbg( p_demux, "    - audio codec not supported=%4.4s",
1432                      (char*)&fmt.i_codec );
1433             break;
1434
1435         default:
1436             msg_Dbg( p_demux, "    - unknown audio codec=%4.4s",
1437                      (char*)&fmt.i_codec );
1438             break;
1439         }
1440
1441         if( fmt.i_codec != 0 )
1442         {
1443             msg_Dbg( p_demux, "        - extra data=%d", fmt.i_extra );
1444
1445             tk = malloc( sizeof( real_track_t ) );
1446             tk->i_id = i_num;
1447             tk->fmt = fmt;
1448             tk->i_frame = 0;
1449             tk->p_frame = NULL;
1450
1451             tk->i_subpacket_h = i_subpacket_h;
1452             tk->i_subpacket_size = i_subpacket_size;
1453             tk->i_coded_frame_size = i_coded_frame_size;
1454             tk->i_frame_size = i_frame_size;
1455
1456             tk->i_out_subpacket = 0;
1457             tk->i_subpacket = 0;
1458             tk->i_subpackets = 0;
1459             tk->p_subpackets = NULL;
1460             tk->p_subpackets_timecode = NULL;
1461             if( fmt.i_codec == VLC_FOURCC('c','o','o','k')
1462              || fmt.i_codec == VLC_FOURCC('a','t','r','c') )
1463             {
1464                 tk->i_subpackets =
1465                     i_subpacket_h * i_frame_size / tk->i_subpacket_size;
1466                 tk->p_subpackets =
1467                     calloc( tk->i_subpackets, sizeof(block_t *) );
1468                 tk->p_subpackets_timecode =
1469                     calloc( tk->i_subpackets , sizeof( int64_t ) );
1470             }
1471             else if( fmt.i_codec == VLC_FOURCC('2','8','_','8') )
1472             {
1473                 tk->i_subpackets =
1474                     i_subpacket_h * i_frame_size / tk->i_coded_frame_size;
1475                 tk->p_subpackets =
1476                     calloc( tk->i_subpackets, sizeof(block_t *) );
1477                 tk->p_subpackets_timecode =
1478                     calloc( tk->i_subpackets , sizeof( int64_t ) );
1479             }
1480
1481             /* Check if the calloc went correctly */
1482             if( tk->p_subpackets == NULL )
1483             {
1484                 tk->i_subpackets = 0;
1485                 msg_Err( p_demux, "Can't alloc subpacket" );
1486                 return VLC_EGENERIC;
1487             }
1488
1489             tk->p_es = es_out_Add( p_demux->out, &fmt );
1490
1491             TAB_APPEND( p_sys->i_track, p_sys->track, tk );
1492         }
1493     }
1494
1495     return VLC_SUCCESS;
1496 }