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