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