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