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