1 /*****************************************************************************
2 * real.c: Real demuxer.
3 *****************************************************************************
4 * Copyright (C) 2004, 2006 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
30 #include <stdlib.h> /* malloc(), free() */
32 #include <vlc_demux.h>
33 #include <vlc_charset.h>
36 /*****************************************************************************
38 *****************************************************************************/
39 static int Open ( vlc_object_t
* );
40 static void Close ( vlc_object_t
* );
43 set_description( _("Real demuxer" ) );
44 set_capability( "demux2", 15 );
45 set_category( CAT_INPUT
);
46 set_subcategory( SUBCAT_INPUT_DEMUX
);
47 set_callbacks( Open
, Close
);
48 add_shortcut( "real" );
52 /*****************************************************************************
54 *****************************************************************************/
68 int i_coded_frame_size
;
73 block_t
**p_subpackets
;
80 int64_t i_data_offset
;
82 uint32_t i_data_packets_count
;
83 uint32_t i_data_packets
;
84 int64_t i_data_offset_next
;
92 char* psz_description
;
97 uint8_t buffer
[65536];
102 static int Demux( demux_t
*p_demux
);
103 static int Control( demux_t
*p_demux
, int i_query
, va_list args
);
105 static int HeaderRead( demux_t
*p_demux
);
106 static int ReadCodecSpecificData( demux_t
*p_demux
, int i_len
, int i_num
);
108 /*****************************************************************************
110 *****************************************************************************/
111 static int Open( vlc_object_t
*p_this
)
113 demux_t
*p_demux
= (demux_t
*)p_this
;
118 if( stream_Peek( p_demux
->s
, &p_peek
, 10 ) < 10 ) return VLC_EGENERIC
;
119 if( strncmp( (char *)p_peek
, ".RMF", 4 ) ) return VLC_EGENERIC
;
121 /* Fill p_demux field */
122 p_demux
->pf_demux
= Demux
;
123 p_demux
->pf_control
= Control
;
124 p_demux
->p_sys
= p_sys
= malloc( sizeof( demux_sys_t
) );
125 memset( p_sys
, 0, sizeof( demux_sys_t
) );
126 p_sys
->i_data_offset
= 0;
132 /* Parse the headers */
133 if( HeaderRead( p_demux
) )
136 msg_Err( p_demux
, "invalid header" );
137 for( i
= 0; i
< p_sys
->i_track
; i
++ )
139 real_track_t
*tk
= p_sys
->track
[i
];
143 es_out_Del( p_demux
->out
, tk
->p_es
);
147 if( p_sys
->i_track
> 0 )
149 free( p_sys
->track
);
158 /*****************************************************************************
160 *****************************************************************************/
161 static void Close( vlc_object_t
*p_this
)
163 demux_t
*p_demux
= (demux_t
*)p_this
;
164 demux_sys_t
*p_sys
= p_demux
->p_sys
;
167 for( i
= 0; i
< p_sys
->i_track
; i
++ )
169 real_track_t
*tk
= p_sys
->track
[i
];
170 int j
= tk
->i_subpackets
;
172 if( tk
->p_frame
) block_Release( tk
->p_frame
);
173 es_format_Clean( &tk
->fmt
);
177 if( tk
->p_subpackets
[ j
] )
178 block_Release( tk
->p_subpackets
[ j
] );
180 if( tk
->i_subpackets
) free( tk
->p_subpackets
);
185 if( p_sys
->psz_title
) free( p_sys
->psz_title
);
186 if( p_sys
->psz_artist
) free( p_sys
->psz_artist
);
187 if( p_sys
->psz_copyright
) free( p_sys
->psz_copyright
);
188 if( p_sys
->psz_description
) free( p_sys
->psz_description
);
190 if( p_sys
->i_track
> 0 ) free( p_sys
->track
);
195 /*****************************************************************************
197 *****************************************************************************/
198 static int Demux( demux_t
*p_demux
)
200 demux_sys_t
*p_sys
= p_demux
->p_sys
;
202 int i_size
, i_id
, i_flags
, i
;
204 real_track_t
*tk
= NULL
;
205 vlc_bool_t b_selected
;
207 if( p_sys
->i_data_packets
>= p_sys
->i_data_packets_count
&&
208 p_sys
->i_data_packets_count
)
210 if( stream_Read( p_demux
->s
, header
, 18 ) < 18 )
214 if( strncmp( (char *)header
, "DATA", 4 ) )
218 p_sys
->i_data_offset
= stream_Tell( p_demux
->s
) - 18;
219 p_sys
->i_data_size
= GetDWBE( &header
[4] );
220 p_sys
->i_data_packets_count
= GetDWBE( &header
[10] );
221 p_sys
->i_data_packets
= 0;
222 p_sys
->i_data_offset_next
= GetDWBE( &header
[14] );
224 msg_Dbg( p_demux
, "entering new DATA packets=%d next=%u",
225 p_sys
->i_data_packets_count
,
226 (uint32_t)p_sys
->i_data_offset_next
);
229 if( stream_Read( p_demux
->s
, header
, 12 ) < 12 ) return 0;
231 i_size
= GetWBE( &header
[2] ) - 12;
232 i_id
= GetWBE( &header
[4] );
233 i_pts
= 1000 * GetDWBE( &header
[6] );
234 i_pts
+= 1000; /* Avoid 0 pts */
235 i_flags
= header
[11]; /* flags 0x02 -> keyframe */
238 msg_Dbg( p_demux
, "packet %d size=%d id=%d pts=%u",
239 p_sys
->i_data_packets
, i_size
, i_id
, (uint32_t)(i_pts
/1000) );
242 p_sys
->i_data_packets
++;
244 stream_Read( p_demux
->s
, p_sys
->buffer
, i_size
);
246 for( i
= 0; i
< p_sys
->i_track
; i
++ )
248 if( p_sys
->track
[i
]->i_id
== i_id
) tk
= p_sys
->track
[i
];
253 msg_Warn( p_demux
, "unknown track id(0x%x)", i_id
);
256 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es
, &b_selected
);
258 if( tk
->fmt
.i_cat
== VIDEO_ES
&& b_selected
)
260 uint8_t *p
= p_sys
->buffer
;
262 while( p
< &p_sys
->buffer
[i_size
- 2] )
271 if( (h
&0xc0) == 0x40 )
275 i_len
= &p_sys
->buffer
[i_size
] - p
;
281 i_subseq
= (*p
++)&0x7f;
283 i_len
= (p
[0] << 8)|p
[1]; p
+= 2;
284 if( (i_len
&0xc000) == 0 )
287 i_len
|= (p
[0] << 8)|p
[1]; p
+= 2;
295 i_offset
= (p
[0] << 8)|p
[1]; p
+= 2;
296 if( (i_offset
&0xc000) == 0 )
299 i_offset
|= (p
[0] << 8)|p
[1]; p
+= 2;
300 i_offset
&= 0x3fffffff;
309 i_copy
= i_len
- i_offset
;
310 if( i_copy
> &p_sys
->buffer
[i_size
] - p
)
312 i_copy
= &p_sys
->buffer
[i_size
] - p
;
314 else if( i_copy
< 0 )
319 msg_Dbg( p_demux
, " - len=%d offset=%d size=%d subseq=%d seqnum=%d",
320 i_len
, i_offset
, i_copy
, i_subseq
, i_seqnum
);
322 if( (h
&0xc0) == 0x80 )
324 /* last fragment -> fixes */
326 i_offset
= i_len
- i_copy
;
327 msg_Dbg( p_demux
, "last fixing copy=%d offset=%d",
332 ( tk
->p_frame
->i_dts
!= i_pts
||
333 tk
->i_frame
!= i_len
) )
335 msg_Dbg( p_demux
, "sending size=%d", tk
->p_frame
->i_buffer
);
337 if( p_sys
->i_pcr
< tk
->p_frame
->i_dts
)
339 p_sys
->i_pcr
= tk
->p_frame
->i_dts
;
341 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
,
342 (int64_t)p_sys
->i_pcr
);
344 es_out_Send( p_demux
->out
, tk
->p_es
, tk
->p_frame
);
350 if( (h
&0xc0) != 0x80 && (h
&0xc0) != 0x00 && !tk
->p_frame
)
358 if( tk
->p_frame
== NULL
)
360 msg_Dbg( p_demux
, "new frame size=%d", i_len
);
362 if( !( tk
->p_frame
= block_New( p_demux
, i_len
+ 8 + 1000) ) )
366 memset( &tk
->p_frame
->p_buffer
[8], 0, i_len
);
367 tk
->p_frame
->i_dts
= i_pts
;
368 tk
->p_frame
->i_pts
= i_pts
;
370 ((uint32_t*)tk
->p_frame
->p_buffer
)[0] = i_len
; /* len */
371 ((uint32_t*)tk
->p_frame
->p_buffer
)[1] = 0; /* chunk counts */
374 if( i_offset
< tk
->i_frame
)
376 int i_ck
= ((uint32_t*)tk
->p_frame
->p_buffer
)[1]++;
378 msg_Dbg( p_demux
, "copying new buffer n=%d offset=%d copy=%d",
379 i_ck
, i_offset
, i_copy
);
381 ((uint32_t*)(tk
->p_frame
->p_buffer
+i_len
+8))[i_ck
] = i_offset
;
383 memcpy( &tk
->p_frame
->p_buffer
[i_offset
+ 8], p
, i_copy
);
388 if( (h
&0xc0) != 0x80 )
397 int i_ck
= ((uint32_t*)tk
->p_frame
->p_buffer
)[1]++;
399 if( (h
&0xc0) == 0x80 )
403 i_offset
= i_len
- i_offset
;
405 ((uint32_t*)(tk
->p_frame
->p_buffer
+i_len
+8))[i_ck
] = i_offset
;
406 memcpy( &tk
->p_frame
->p_buffer
[i_offset
+ 8], p
, i_copy
);
409 if( p_sys
->i_pcr
< tk
->p_frame
->i_dts
)
411 p_sys
->i_pcr
= tk
->p_frame
->i_dts
;
412 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
,
413 (int64_t)p_sys
->i_pcr
);
415 es_out_Send( p_demux
->out
, tk
->p_es
, tk
->p_frame
);
423 ((uint32_t*)(tk
->p_frame
->p_buffer
+i_len
+8))[i_ck
] = i_offset
;
424 memcpy( &tk
->p_frame
->p_buffer
[i_offset
+ 8], p
, i_copy
);
428 if( (h
&0xc0) != 0x00 )
433 if( !( p_frame
= block_New( p_demux
, i_copy
+ 8 + 8 ) ) )
437 p_frame
->i_dts
= i_pts
;
438 p_frame
->i_pts
= i_pts
;
440 ((uint32_t*)p_frame
->p_buffer
)[0] = i_copy
;
441 ((uint32_t*)p_frame
->p_buffer
)[1] = 1;
442 ((uint32_t*)(p_frame
->p_buffer
+i_copy
+8))[0] = 0;
443 memcpy( &p_frame
->p_buffer
[8], p
, i_copy
);
447 if( p_sys
->i_pcr
< p_frame
->i_dts
)
449 p_sys
->i_pcr
= p_frame
->i_dts
;
450 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
,
451 (int64_t)p_sys
->i_pcr
);
453 es_out_Send( p_demux
->out
, tk
->p_es
, p_frame
);
459 if( !( tk
->p_frame
= block_New( p_demux
, i_len
+ 8 + 1000) ) )
463 memset( &tk
->p_frame
->p_buffer
[8], 0, i_len
);
464 tk
->p_frame
->i_dts
= i_pts
;
465 tk
->p_frame
->i_pts
= i_pts
;
467 ((uint32_t*)tk
->p_frame
->p_buffer
)[0] = i_len
; /* len */
468 ((uint32_t*)tk
->p_frame
->p_buffer
)[1] = 1; /* chunk counts */
469 ((uint32_t*)(tk
->p_frame
->p_buffer
+i_len
+8))[0] = i_offset
;
470 memcpy( &tk
->p_frame
->p_buffer
[i_offset
+ 8], p
, i_copy
);
477 else if( tk
->fmt
.i_cat
== AUDIO_ES
&& b_selected
)
480 if( p_sys
->i_pcr
< i_pts
)
482 p_sys
->i_pcr
= i_pts
;
483 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
,
484 (int64_t)p_sys
->i_pcr
);
487 if( tk
->fmt
.i_codec
== VLC_FOURCC( 'm', 'p', '4', 'a' ) )
489 int i_sub
= (p_sys
->buffer
[1] >> 4)&0x0f;
490 uint8_t *p_sub
= &p_sys
->buffer
[2+2*i_sub
];
493 for( i
= 0; i
< i_sub
; i
++ )
495 int i_sub_size
= GetWBE( &p_sys
->buffer
[2+i
*2]);
496 block_t
*p_block
= block_New( p_demux
, i_sub_size
);
499 memcpy( p_block
->p_buffer
, p_sub
, i_sub_size
);
503 p_block
->i_pts
= ( i
== 0 ? i_pts
: 0 );
505 es_out_Send( p_demux
->out
, tk
->p_es
, p_block
);
509 else if( tk
->fmt
.i_codec
== VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
510 tk
->fmt
.i_codec
== VLC_FOURCC('2','8','_','8') )
512 uint8_t *p_buf
= p_sys
->buffer
;
513 int y
= tk
->i_subpacket
/ (tk
->i_frame_size
/tk
->i_subpacket_size
);
517 if( i_flags
& 2 ) y
= tk
->i_subpacket
= 0;
519 if( tk
->fmt
.i_codec
== VLC_FOURCC( 'c', 'o', 'o', 'k' ) )
520 for( i
= 0; i
< tk
->i_frame_size
/ tk
->i_subpacket_size
; i
++ )
522 block_t
*p_block
= block_New( p_demux
, tk
->i_subpacket_size
);
523 memcpy( p_block
->p_buffer
, p_buf
, tk
->i_subpacket_size
);
524 p_buf
+= tk
->i_subpacket_size
;
526 i_index
= tk
->i_subpacket_h
* i
+
527 ((tk
->i_subpacket_h
+ 1) / 2) * (y
&1) + (y
>>1);
529 p_block
->i_dts
= p_block
->i_pts
= i_pts
;
530 tk
->p_subpackets
[i_index
] = p_block
;
534 if( tk
->fmt
.i_codec
== VLC_FOURCC('2','8','_','8') )
535 for( i
= 0; i
< tk
->i_subpacket_h
/ 2; i
++ )
537 block_t
*p_block
= block_New( p_demux
, tk
->i_coded_frame_size
);
538 memcpy( p_block
->p_buffer
, p_buf
, tk
->i_coded_frame_size
);
539 p_buf
+= tk
->i_coded_frame_size
;
541 i_index
= (i
* 2 * tk
->i_frame_size
) /
542 tk
->i_coded_frame_size
+ y
;
544 p_block
->i_dts
= p_block
->i_pts
= i_pts
;
545 tk
->p_subpackets
[i_index
] = p_block
;
549 while( tk
->i_out_subpacket
!= tk
->i_subpackets
&&
550 tk
->p_subpackets
[tk
->i_out_subpacket
] )
552 block_t
*p_block
= tk
->p_subpackets
[tk
->i_out_subpacket
];
553 tk
->p_subpackets
[tk
->i_out_subpacket
] = 0;
555 if( tk
->i_out_subpacket
) p_block
->i_dts
= p_block
->i_pts
= 0;
556 es_out_Send( p_demux
->out
, tk
->p_es
, p_block
);
558 tk
->i_out_subpacket
++;
561 if( tk
->i_subpacket
== tk
->i_subpackets
&&
562 tk
->i_out_subpacket
!= tk
->i_subpackets
)
564 msg_Warn( p_demux
, "i_subpacket != i_out_subpacket, "
565 "this shouldn't happen" );
568 if( tk
->i_subpacket
== tk
->i_subpackets
)
571 tk
->i_out_subpacket
= 0;
576 block_t
*p_block
= block_New( p_demux
, i_size
);
578 if( tk
->fmt
.i_codec
== VLC_FOURCC( 'a', '5', '2', ' ' ) )
580 uint8_t *src
= p_sys
->buffer
;
581 uint8_t *dst
= p_block
->p_buffer
;
584 while( dst
< &p_block
->p_buffer
[i_size
- 1])
594 memcpy( p_block
->p_buffer
, p_sys
->buffer
, i_size
);
596 p_block
->i_dts
= p_block
->i_pts
= i_pts
;
597 es_out_Send( p_demux
->out
, tk
->p_es
, p_block
);
605 /*****************************************************************************
607 *****************************************************************************/
608 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
610 demux_sys_t
*p_sys
= p_demux
->p_sys
;
620 case DEMUX_GET_POSITION
:
621 pf
= (double*) va_arg( args
, double* );
622 i64
= stream_Size( p_demux
->s
);
625 *pf
= (double)stream_Tell( p_demux
->s
) / (double)i64
;
633 case DEMUX_SET_POSITION
:
634 f
= (double) va_arg( args
, double );
635 i64
= stream_Size( p_demux
->s
);
637 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
639 return stream_Seek( p_demux
->s
, (int64_t)(i64
* f
) );
642 pi64
= (int64_t*)va_arg( args
, int64_t * );
643 if( p_sys
->i_mux_rate
> 0 )
645 *pi64
= (int64_t)1000000 * ( stream_Tell( p_demux
->s
) / 50 ) / p_sys
->i_mux_rate
;
652 case DEMUX_GET_LENGTH
:
653 pi64
= (int64_t*)va_arg( args
, int64_t * );
655 /* the commented following lines are fen's implementation, which doesn't seem to
656 * work for one reason or another -- FK */
657 /*if( p_sys->i_mux_rate > 0 )
659 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
662 if( p_sys
->i_our_duration
> 0 )
664 /* our stored duration is in ms, so... */
665 *pi64
= (int64_t)1000 * p_sys
->i_our_duration
;
674 vlc_meta_t
*p_meta
= (vlc_meta_t
*)va_arg( args
, vlc_meta_t
* );
676 /* the core will crash if we provide NULL strings, so check
677 * every string first */
678 if( p_sys
->psz_title
)
679 vlc_meta_SetTitle( p_meta
, p_sys
->psz_title
);
680 if( p_sys
->psz_artist
)
681 vlc_meta_SetArtist( p_meta
, p_sys
->psz_artist
);
682 if( p_sys
->psz_copyright
)
683 vlc_meta_SetCopyright( p_meta
, p_sys
->psz_copyright
);
684 if( p_sys
->psz_description
)
685 vlc_meta_SetDescription( p_meta
, p_sys
->psz_description
);
697 /*****************************************************************************
699 *****************************************************************************/
700 static int HeaderRead( demux_t
*p_demux
)
702 demux_sys_t
*p_sys
= p_demux
->p_sys
;
703 uint8_t header
[100]; /* FIXME */
712 /* Read the header */
713 if( stream_Read( p_demux
->s
, header
, 10 ) < 10 )
717 i_id
= VLC_FOURCC( header
[0], header
[1], header
[2], header
[3] );
718 i_size
= GetDWBE( &header
[4] );
719 i_version
= GetWBE( &header
[8] );
721 msg_Dbg( p_demux
, "object %4.4s size=%d version=%d",
722 (char*)&i_id
, i_size
, i_version
);
724 if( i_size
< 10 && i_id
!= VLC_FOURCC('D','A','T','A') )
726 msg_Dbg( p_demux
, "invalid size for object %4.4s", (char*)&i_id
);
729 i_skip
= i_size
- 10;
731 if( i_id
== VLC_FOURCC('.','R','M','F') )
733 if( stream_Read( p_demux
->s
, header
, 8 ) < 8 ) return VLC_EGENERIC
;
734 msg_Dbg( p_demux
, " - file version=0x%x num headers=%d",
735 GetDWBE( &header
[0] ), GetDWBE( &header
[4] ) );
739 else if( i_id
== VLC_FOURCC('P','R','O','P') )
743 if( stream_Read(p_demux
->s
, header
, 40) < 40 ) return VLC_EGENERIC
;
745 msg_Dbg( p_demux
, " - max bitrate=%d avg bitrate=%d",
746 GetDWBE(&header
[0]), GetDWBE(&header
[4]) );
747 msg_Dbg( p_demux
, " - max packet size=%d avg bitrate=%d",
748 GetDWBE(&header
[8]), GetDWBE(&header
[12]) );
749 msg_Dbg( p_demux
, " - packets count=%d", GetDWBE(&header
[16]) );
750 msg_Dbg( p_demux
, " - duration=%d ms", GetDWBE(&header
[20]) );
751 msg_Dbg( p_demux
, " - preroll=%d ms", GetDWBE(&header
[24]) );
752 msg_Dbg( p_demux
, " - index offset=%d", GetDWBE(&header
[28]) );
753 msg_Dbg( p_demux
, " - data offset=%d", GetDWBE(&header
[32]) );
754 msg_Dbg( p_demux
, " - num streams=%d", GetWBE(&header
[36]) );
756 /* set the duration for export in control */
757 p_sys
->i_our_duration
= (int)GetDWBE(&header
[20]);
759 i_flags
= GetWBE(&header
[38]);
760 msg_Dbg( p_demux
, " - flags=0x%x %s%s%s",
762 i_flags
&0x0001 ? "PN_SAVE_ENABLED " : "",
763 i_flags
&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
764 i_flags
&0x0004 ? "PN_LIVE_BROADCAST" : "" );
767 else if( i_id
== VLC_FOURCC('C','O','N','T') )
772 /* FIXME FIXME: should convert from whatever the character
773 * encoding of the input meta data is to UTF-8. */
775 stream_Read( p_demux
->s
, header
, 2 );
776 if( ( i_len
= GetWBE( header
) ) > 0 )
778 psz
= malloc( i_len
+ 1 );
779 stream_Read( p_demux
->s
, psz
, i_len
);
782 msg_Dbg( p_demux
, " - title=`%s'", psz
);
784 asprintf( &p_sys
->psz_title
, psz
);
790 stream_Read( p_demux
->s
, header
, 2 );
791 if( ( i_len
= GetWBE( header
) ) > 0 )
793 psz
= malloc( i_len
+ 1 );
794 stream_Read( p_demux
->s
, psz
, i_len
);
797 msg_Dbg( p_demux
, " - author=`%s'", psz
);
799 asprintf( &p_sys
->psz_artist
, psz
);
805 stream_Read( p_demux
->s
, header
, 2 );
806 if( ( i_len
= GetWBE( header
) ) > 0 )
808 psz
= malloc( i_len
+ 1 );
809 stream_Read( p_demux
->s
, psz
, i_len
);
812 msg_Dbg( p_demux
, " - copyright=`%s'", psz
);
814 asprintf( &p_sys
->psz_copyright
, psz
);
820 stream_Read( p_demux
->s
, header
, 2 );
821 if( ( i_len
= GetWBE( header
) ) > 0 )
823 psz
= malloc( i_len
+ 1 );
824 stream_Read( p_demux
->s
, psz
, i_len
);
827 msg_Dbg( p_demux
, " - comment=`%s'", psz
);
829 asprintf( &p_sys
->psz_description
, psz
);
835 else if( i_id
== VLC_FOURCC('M','D','P','R') )
837 /* Media properties header */
842 if( stream_Read(p_demux
->s
, header
, 30) < 30 ) return VLC_EGENERIC
;
843 i_num
= GetWBE( header
);
844 msg_Dbg( p_demux
, " - id=0x%x", i_num
);
845 msg_Dbg( p_demux
, " - max bitrate=%d avg bitrate=%d",
846 GetDWBE(&header
[2]), GetDWBE(&header
[6]) );
847 msg_Dbg( p_demux
, " - max packet size=%d avg packet size=%d",
848 GetDWBE(&header
[10]), GetDWBE(&header
[14]) );
849 msg_Dbg( p_demux
, " - start time=%d", GetDWBE(&header
[18]) );
850 msg_Dbg( p_demux
, " - preroll=%d", GetDWBE(&header
[22]) );
851 msg_Dbg( p_demux
, " - duration=%d", GetDWBE(&header
[26]) );
855 stream_Read( p_demux
->s
, header
, 1 );
856 if( ( i_len
= header
[0] ) > 0 )
858 psz
= malloc( i_len
+ 1 );
859 stream_Read( p_demux
->s
, psz
, i_len
);
862 msg_Dbg( p_demux
, " - name=`%s'", psz
);
868 stream_Read( p_demux
->s
, header
, 1 );
869 if( ( i_len
= header
[0] ) > 0 )
871 psz
= malloc( i_len
+ 1 );
872 stream_Read( p_demux
->s
, psz
, i_len
);
875 msg_Dbg( p_demux
, " - mime=`%s'", psz
);
881 stream_Read( p_demux
->s
, header
, 4 );
882 if( ( i_len
= GetDWBE( header
) ) > 0 )
884 ReadCodecSpecificData( p_demux
, i_len
, i_num
);
885 stream_Read( p_demux
->s
, NULL
, i_len
);
891 else if( i_id
== VLC_FOURCC('D','A','T','A') )
893 stream_Read( p_demux
->s
, header
, 8 );
895 p_sys
->i_data_offset
= stream_Tell( p_demux
->s
) - 10;
896 p_sys
->i_data_size
= i_size
;
897 p_sys
->i_data_packets_count
= GetDWBE( header
);
898 p_sys
->i_data_packets
= 0;
899 p_sys
->i_data_offset_next
= GetDWBE( &header
[4] );
901 msg_Dbg( p_demux
, " - packets count=%d next=%u",
902 p_sys
->i_data_packets_count
,
903 (uint32_t)p_sys
->i_data_offset_next
);
905 /* we have finished the header */
911 msg_Dbg( p_demux
, "unknown chunk" );
914 if( i_skip
< 0 ) return VLC_EGENERIC
;
915 stream_Read( p_demux
->s
, NULL
, i_skip
);
918 /* TODO read index if possible */
923 static int ReadCodecSpecificData( demux_t
*p_demux
, int i_len
, int i_num
)
925 demux_sys_t
*p_sys
= p_demux
->p_sys
;
930 msg_Dbg( p_demux
, " - specific data len=%d", i_len
);
931 if( stream_Peek(p_demux
->s
, &p_peek
, i_len
) < i_len
) return VLC_EGENERIC
;
933 if( !strncmp( (char *)&p_peek
[4], "VIDO", 4 ) )
935 es_format_Init( &fmt
, VIDEO_ES
, VLC_FOURCC( p_peek
[8], p_peek
[9],
936 p_peek
[10], p_peek
[11] ) );
937 fmt
.video
.i_width
= GetWBE( &p_peek
[12] );
938 fmt
.video
.i_height
= GetWBE( &p_peek
[14] );
941 fmt
.p_extra
= malloc( 8 );
942 ((uint32_t*)fmt
.p_extra
)[0] = GetDWBE( &p_peek
[26] );
943 ((uint32_t*)fmt
.p_extra
)[1] = GetDWBE( &p_peek
[30] );
945 msg_Dbg( p_demux
, " - video 0x%08x 0x%08x",
946 ((uint32_t*)fmt
.p_extra
)[0], ((uint32_t*)fmt
.p_extra
)[1] );
948 if( GetDWBE( &p_peek
[30] ) == 0x10003000 ||
949 GetDWBE( &p_peek
[30] ) == 0x10003001 )
951 fmt
.i_codec
= VLC_FOURCC( 'R','V','1','3' );
953 else if( GetDWBE( &p_peek
[30] ) == 0x20001000 ||
954 GetDWBE( &p_peek
[30] ) == 0x20100001 ||
955 GetDWBE( &p_peek
[30] ) == 0x20200002 )
957 fmt
.i_codec
= VLC_FOURCC( 'R','V','2','0' );
959 else if( GetDWBE( &p_peek
[30] ) == 0x30202002 )
961 fmt
.i_codec
= VLC_FOURCC( 'R','V','3','0' );
963 else if( GetDWBE( &p_peek
[30] ) == 0x40000000 )
965 fmt
.i_codec
= VLC_FOURCC( 'R','V','4','0' );
968 msg_Dbg( p_demux
, " - video %4.4s %dx%d",
969 (char*)&fmt
.i_codec
, fmt
.video
.i_width
, fmt
.video
.i_height
);
971 tk
= malloc( sizeof( real_track_t
) );
972 tk
->i_out_subpacket
= 0;
974 tk
->i_subpackets
= 0;
975 tk
->p_subpackets
= NULL
;
980 tk
->p_es
= es_out_Add( p_demux
->out
, &fmt
);
982 TAB_APPEND( p_sys
->i_track
, p_sys
->track
, tk
);
984 else if( !strncmp( (char *)p_peek
, ".ra\xfd", 4 ) )
986 int i_version
= GetWBE( &p_peek
[4] );
987 int i_header_size
, i_flavor
, i_coded_frame_size
, i_subpacket_h
;
988 int i_frame_size
, i_subpacket_size
;
990 msg_Dbg( p_demux
, " - audio version=%d", i_version
);
993 es_format_Init( &fmt
, AUDIO_ES
, 0 );
997 msg_Dbg( p_demux
, " - audio version 3 is not supported!" );
1001 p_peek
+= 2; /* 00 00 */
1002 p_peek
+= 4; /* .ra4 or .ra5 */
1003 p_peek
+= 4; /* ?? */
1004 p_peek
+= 2; /* version (4 or 5) */
1005 i_header_size
= GetDWBE( p_peek
); p_peek
+= 4; /* header size */
1006 i_flavor
= GetWBE( p_peek
); p_peek
+= 2; /* codec flavor */
1007 i_coded_frame_size
= GetDWBE( p_peek
); p_peek
+= 4;
1008 p_peek
+= 4; /* ?? */
1009 p_peek
+= 4; /* ?? */
1010 p_peek
+= 4; /* ?? */
1011 i_subpacket_h
= GetWBE( p_peek
); p_peek
+= 2;
1012 i_frame_size
= GetWBE( p_peek
); p_peek
+= 2;
1013 i_subpacket_size
= GetWBE( p_peek
); p_peek
+= 2;
1014 p_peek
+= 2; /* ?? */
1016 if( i_version
== 5 ) p_peek
+= 6; /* 0, srate, 0 */
1018 fmt
.audio
.i_rate
= GetWBE( p_peek
); p_peek
+= 2;
1019 p_peek
+= 2; /* ?? */
1020 fmt
.audio
.i_bitspersample
= GetWBE( p_peek
); p_peek
+= 2;
1021 fmt
.audio
.i_channels
= GetWBE( p_peek
); p_peek
+= 2;
1022 fmt
.audio
.i_blockalign
= i_frame_size
;
1024 if( i_version
== 5 )
1026 p_peek
+= 4; /* genr */
1027 memcpy( (char *)&fmt
.i_codec
, p_peek
, 4 ); p_peek
+= 4;
1031 p_peek
+= p_peek
[0] + 1; /* descr 1 */
1032 memcpy( (char *)&fmt
.i_codec
, p_peek
+ 1, 4 ); /* descr 2 */
1033 p_peek
+= p_peek
[0] + 1;
1036 msg_Dbg( p_demux
, " - audio codec=%4.4s channels=%d rate=%dHz",
1037 (char*)&fmt
.i_codec
, fmt
.audio
.i_channels
, fmt
.audio
.i_rate
);
1039 p_peek
+= 3; /* ?? */
1040 if( i_version
== 5 ) p_peek
++;
1042 switch( fmt
.i_codec
)
1044 case VLC_FOURCC( 'd', 'n', 'e', 't' ):
1045 fmt
.i_codec
= VLC_FOURCC( 'a', '5', '2', ' ' );
1048 case VLC_FOURCC( 'r', 'a', 'a', 'c' ):
1049 case VLC_FOURCC( 'r', 'a', 'c', 'p' ):
1050 fmt
.i_extra
= GetDWBE( p_peek
); p_peek
+= 4;
1051 if( fmt
.i_extra
> 0 ) { fmt
.i_extra
--; p_peek
++; }
1052 if( fmt
.i_extra
> 0 )
1054 fmt
.p_extra
= malloc( fmt
.i_extra
);
1055 memcpy( fmt
.p_extra
, p_peek
, fmt
.i_extra
);
1058 fmt
.i_codec
= VLC_FOURCC( 'm', 'p', '4', 'a' );
1061 case VLC_FOURCC('c','o','o','k'):
1062 fmt
.audio
.i_blockalign
= i_subpacket_size
;
1063 if( !(fmt
.i_extra
= GetDWBE( p_peek
)) ) break;
1064 fmt
.p_extra
= malloc( fmt
.i_extra
);
1065 memcpy( fmt
.p_extra
, p_peek
+ 4, fmt
.i_extra
);
1068 case VLC_FOURCC('2','8','_','8'):
1069 fmt
.audio
.i_blockalign
= i_coded_frame_size
;
1073 msg_Dbg( p_demux
, " - unknown audio codec=%4.4s",
1074 (char*)&fmt
.i_codec
);
1078 if( fmt
.i_codec
!= 0 )
1082 msg_Dbg( p_demux
, " - extra data=%d", fmt
.i_extra
);
1084 tk
= malloc( sizeof( real_track_t
) );
1090 tk
->i_subpacket_h
= i_subpacket_h
;
1091 tk
->i_subpacket_size
= i_subpacket_size
;
1092 tk
->i_coded_frame_size
= i_coded_frame_size
;
1093 tk
->i_frame_size
= i_frame_size
;
1095 tk
->i_out_subpacket
= 0;
1096 tk
->i_subpacket
= 0;
1097 tk
->i_subpackets
= 0;
1098 tk
->p_subpackets
= NULL
;
1099 if( fmt
.i_codec
== VLC_FOURCC('c','o','o','k') )
1102 i_subpacket_h
* i_frame_size
/ tk
->i_subpacket_size
;
1104 malloc( tk
->i_subpackets
* sizeof(block_t
*) );
1106 else if( fmt
.i_codec
== VLC_FOURCC('2','8','_','8') )
1109 i_subpacket_h
* i_frame_size
/ tk
->i_coded_frame_size
;
1111 malloc( tk
->i_subpackets
* sizeof(block_t
*) );
1114 for( i
= 0; i
< tk
->i_subpackets
; i
++ ) tk
->p_subpackets
[i
] = NULL
;
1116 tk
->p_es
= es_out_Add( p_demux
->out
, &fmt
);
1118 TAB_APPEND( p_sys
->i_track
, p_sys
->track
, tk
);