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