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