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 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <vlc/input.h>
33 /*****************************************************************************
35 *****************************************************************************/
36 static int Open ( vlc_object_t * );
37 static void Close ( vlc_object_t * );
40 set_description( _("Real demuxer" ) );
41 set_capability( "demux2", 15 );
42 set_category( CAT_INPUT );
43 set_subcategory( SUBCAT_INPUT_DEMUX );
44 set_callbacks( Open, Close );
45 add_shortcut( "real" );
49 /*****************************************************************************
51 *****************************************************************************/
65 int i_coded_frame_size;
70 block_t **p_subpackets;
77 int64_t i_data_offset;
79 uint32_t i_data_packets_count;
80 uint32_t i_data_packets;
81 int64_t i_data_offset_next;
89 char* psz_description;
94 uint8_t buffer[65536];
99 static int Demux( demux_t *p_demux );
100 static int Control( demux_t *p_demux, int i_query, va_list args );
102 static int HeaderRead( demux_t *p_demux );
103 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num );
105 /*****************************************************************************
107 *****************************************************************************/
108 static int Open( vlc_object_t *p_this )
110 demux_t *p_demux = (demux_t*)p_this;
115 if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) return VLC_EGENERIC;
116 if( strncmp( (char *)p_peek, ".RMF", 4 ) ) return VLC_EGENERIC;
118 /* Fill p_demux field */
119 p_demux->pf_demux = Demux;
120 p_demux->pf_control = Control;
121 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
122 memset( p_sys, 0, sizeof( demux_sys_t ) );
123 p_sys->i_data_offset = 0;
129 /* Parse the headers */
130 if( HeaderRead( p_demux ) )
133 msg_Err( p_demux, "invalid header" );
134 for( i = 0; i < p_sys->i_track; i++ )
136 real_track_t *tk = p_sys->track[i];
140 es_out_Del( p_demux->out, tk->p_es );
144 if( p_sys->i_track > 0 )
146 free( p_sys->track );
155 /*****************************************************************************
157 *****************************************************************************/
158 static void Close( vlc_object_t *p_this )
160 demux_t *p_demux = (demux_t*)p_this;
161 demux_sys_t *p_sys = p_demux->p_sys;
164 for( i = 0; i < p_sys->i_track; i++ )
166 real_track_t *tk = p_sys->track[i];
167 int j = tk->i_subpackets;
169 if( tk->p_frame ) block_Release( tk->p_frame );
170 es_format_Clean( &tk->fmt );
174 if( tk->p_subpackets[ j ] )
175 block_Release( tk->p_subpackets[ j ] );
177 if( !tk->i_subpackets ) free( tk->p_subpackets );
182 if( p_sys->i_track > 0 ) free( p_sys->track );
187 /*****************************************************************************
189 *****************************************************************************/
190 static int Demux( demux_t *p_demux )
192 demux_sys_t *p_sys = p_demux->p_sys;
194 int i_size, i_id, i_flags, i;
196 real_track_t *tk = NULL;
197 vlc_bool_t b_selected;
199 if( p_sys->i_data_packets >= p_sys->i_data_packets_count &&
200 p_sys->i_data_packets_count )
202 if( stream_Read( p_demux->s, header, 18 ) < 18 )
206 if( strncmp( (char *)header, "DATA", 4 ) )
210 p_sys->i_data_offset = stream_Tell( p_demux->s ) - 18;
211 p_sys->i_data_size = GetDWBE( &header[4] );
212 p_sys->i_data_packets_count = GetDWBE( &header[10] );
213 p_sys->i_data_packets = 0;
214 p_sys->i_data_offset_next = GetDWBE( &header[14] );
216 msg_Dbg( p_demux, "entering new DATA packets=%d next=%u",
217 p_sys->i_data_packets_count,
218 (uint32_t)p_sys->i_data_offset_next );
221 if( stream_Read( p_demux->s, header, 12 ) < 12 ) return 0;
223 i_size = GetWBE( &header[2] ) - 12;
224 i_id = GetWBE( &header[4] );
225 i_pts = 1000 * GetDWBE( &header[6] );
226 i_pts += 1000; /* Avoid 0 pts */
227 i_flags= header[11]; /* flags 0x02 -> keyframe */
230 msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u",
231 p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) );
234 p_sys->i_data_packets++;
236 stream_Read( p_demux->s, p_sys->buffer, i_size );
238 for( i = 0; i < p_sys->i_track; i++ )
240 if( p_sys->track[i]->i_id == i_id ) tk = p_sys->track[i];
245 msg_Warn( p_demux, "unknown track id(0x%x)", i_id );
248 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b_selected );
250 if( tk->fmt.i_cat == VIDEO_ES && b_selected )
252 uint8_t *p = p_sys->buffer;
254 while( p < &p_sys->buffer[i_size - 2] )
263 if( (h&0xc0) == 0x40 )
267 i_len = &p_sys->buffer[i_size] - p;
273 i_subseq = (*p++)&0x7f;
275 i_len = (p[0] << 8)|p[1]; p += 2;
276 if( (i_len&0xc000) == 0 )
279 i_len |= (p[0] << 8)|p[1]; p += 2;
287 i_offset = (p[0] << 8)|p[1]; p += 2;
288 if( (i_offset&0xc000) == 0 )
291 i_offset |= (p[0] << 8)|p[1]; p += 2;
292 i_offset &= 0x3fffffff;
301 i_copy = i_len - i_offset;
302 if( i_copy > &p_sys->buffer[i_size] - p )
304 i_copy = &p_sys->buffer[i_size] - p;
306 else if( i_copy < 0 )
311 msg_Dbg( p_demux, " - len=%d offset=%d size=%d subseq=%d seqnum=%d",
312 i_len, i_offset, i_copy, i_subseq, i_seqnum );
314 if( (h&0xc0) == 0x80 )
316 /* last fragment -> fixes */
318 i_offset = i_len - i_copy;
319 msg_Dbg( p_demux, "last fixing copy=%d offset=%d",
324 ( tk->p_frame->i_dts != i_pts ||
325 tk->i_frame != i_len ) )
327 msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer );
329 if( p_sys->i_pcr < tk->p_frame->i_dts )
331 p_sys->i_pcr = tk->p_frame->i_dts;
333 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
334 (int64_t)p_sys->i_pcr );
336 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
342 if( (h&0xc0) != 0x80 && (h&0xc0) != 0x00 && !tk->p_frame )
350 if( tk->p_frame == NULL )
352 msg_Dbg( p_demux, "new frame size=%d", i_len );
354 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
358 memset( &tk->p_frame->p_buffer[8], 0, i_len );
359 tk->p_frame->i_dts = i_pts;
360 tk->p_frame->i_pts = i_pts;
362 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len; /* len */
363 ((uint32_t*)tk->p_frame->p_buffer)[1] = 0; /* chunk counts */
366 if( i_offset < tk->i_frame)
368 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
370 msg_Dbg( p_demux, "copying new buffer n=%d offset=%d copy=%d",
371 i_ck, i_offset, i_copy );
373 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
375 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
380 if( (h&0xc0) != 0x80 )
389 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
391 if( (h&0xc0) == 0x80 )
395 i_offset = i_len - i_offset;
397 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
398 memcpy( &tk->p_frame->p_buffer[i_offset+ 8], p, i_copy );
401 if( p_sys->i_pcr < tk->p_frame->i_dts )
403 p_sys->i_pcr = tk->p_frame->i_dts;
404 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
405 (int64_t)p_sys->i_pcr );
407 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
415 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
416 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
420 if( (h&0xc0) != 0x00 )
425 if( !( p_frame = block_New( p_demux, i_copy + 8 + 8 ) ) )
429 p_frame->i_dts = i_pts;
430 p_frame->i_pts = i_pts;
432 ((uint32_t*)p_frame->p_buffer)[0] = i_copy;
433 ((uint32_t*)p_frame->p_buffer)[1] = 1;
434 ((uint32_t*)(p_frame->p_buffer+i_copy+8))[0] = 0;
435 memcpy( &p_frame->p_buffer[8], p, i_copy );
439 if( p_sys->i_pcr < p_frame->i_dts )
441 p_sys->i_pcr = p_frame->i_dts;
442 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
443 (int64_t)p_sys->i_pcr );
445 es_out_Send( p_demux->out, tk->p_es, p_frame );
451 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
455 memset( &tk->p_frame->p_buffer[8], 0, i_len );
456 tk->p_frame->i_dts = i_pts;
457 tk->p_frame->i_pts = i_pts;
459 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len; /* len */
460 ((uint32_t*)tk->p_frame->p_buffer)[1] = 1; /* chunk counts */
461 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[0] = i_offset;
462 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
469 else if( tk->fmt.i_cat == AUDIO_ES && b_selected )
472 if( p_sys->i_pcr < i_pts )
474 p_sys->i_pcr = i_pts;
475 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
476 (int64_t)p_sys->i_pcr );
479 if( tk->fmt.i_codec == VLC_FOURCC( 'm', 'p', '4', 'a' ) )
481 int i_sub = (p_sys->buffer[1] >> 4)&0x0f;
482 uint8_t *p_sub = &p_sys->buffer[2+2*i_sub];
485 for( i = 0; i < i_sub; i++ )
487 int i_sub_size = GetWBE( &p_sys->buffer[2+i*2]);
488 block_t *p_block = block_New( p_demux, i_sub_size );
491 memcpy( p_block->p_buffer, p_sub, i_sub_size );
495 p_block->i_pts = ( i == 0 ? i_pts : 0 );
497 es_out_Send( p_demux->out, tk->p_es, p_block );
501 else if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
502 tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
504 uint8_t *p_buf = p_sys->buffer;
505 int y = tk->i_subpacket / (tk->i_frame_size /tk->i_subpacket_size);
509 if( i_flags & 2 ) y = tk->i_subpacket = 0;
511 if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) )
512 for( i = 0; i < tk->i_frame_size / tk->i_subpacket_size; i++ )
514 block_t *p_block = block_New( p_demux, tk->i_subpacket_size );
515 memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size );
516 p_buf += tk->i_subpacket_size;
518 i_index = tk->i_subpacket_h * i +
519 ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1);
521 p_block->i_dts = p_block->i_pts = i_pts;
522 tk->p_subpackets[i_index] = p_block;
526 if( tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
527 for( i = 0; i < tk->i_subpacket_h / 2; i++ )
529 block_t *p_block = block_New( p_demux, tk->i_coded_frame_size);
530 memcpy( p_block->p_buffer, p_buf, tk->i_coded_frame_size );
531 p_buf += tk->i_coded_frame_size;
533 i_index = (i * 2 * tk->i_frame_size) /
534 tk->i_coded_frame_size + y;
536 p_block->i_dts = p_block->i_pts = i_pts;
537 tk->p_subpackets[i_index] = p_block;
541 while( tk->i_out_subpacket != tk->i_subpackets &&
542 tk->p_subpackets[tk->i_out_subpacket] )
544 block_t *p_block = tk->p_subpackets[tk->i_out_subpacket];
545 tk->p_subpackets[tk->i_out_subpacket] = 0;
547 if( tk->i_out_subpacket ) p_block->i_dts = p_block->i_pts = 0;
548 es_out_Send( p_demux->out, tk->p_es, p_block );
550 tk->i_out_subpacket++;
553 if( tk->i_subpacket == tk->i_subpackets &&
554 tk->i_out_subpacket != tk->i_subpackets )
556 msg_Warn( p_demux, "i_subpacket != i_out_subpacket, "
557 "this shouldn't happen" );
560 if( tk->i_subpacket == tk->i_subpackets )
563 tk->i_out_subpacket = 0;
568 block_t *p_block = block_New( p_demux, i_size );
570 if( tk->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', ' ' ) )
572 uint8_t *src = p_sys->buffer;
573 uint8_t *dst = p_block->p_buffer;
576 while( dst < &p_block->p_buffer[i_size- 1])
586 memcpy( p_block->p_buffer, p_sys->buffer, i_size );
588 p_block->i_dts = p_block->i_pts = i_pts;
589 es_out_Send( p_demux->out, tk->p_es, p_block );
597 /*****************************************************************************
599 *****************************************************************************/
600 static int Control( demux_t *p_demux, int i_query, va_list args )
602 demux_sys_t *p_sys = p_demux->p_sys;
612 case DEMUX_GET_POSITION:
613 pf = (double*) va_arg( args, double* );
614 i64 = stream_Size( p_demux->s );
617 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
625 case DEMUX_SET_POSITION:
626 f = (double) va_arg( args, double );
627 i64 = stream_Size( p_demux->s );
629 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
631 return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
634 pi64 = (int64_t*)va_arg( args, int64_t * );
635 if( p_sys->i_mux_rate > 0 )
637 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
644 case DEMUX_GET_LENGTH:
645 pi64 = (int64_t*)va_arg( args, int64_t * );
647 /* the commented following lines are fen's implementation, which doesn't seem to
648 * work for one reason or another -- FK */
649 /*if( p_sys->i_mux_rate > 0 )
651 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
654 if( p_sys->i_our_duration > 0 )
656 /* our stored duration is in ms, so... */
657 *pi64 = (int64_t)1000 * p_sys->i_our_duration;
666 vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
668 /* the core will crash if we provide NULL strings, so check
669 * every string first */
670 if( p_sys->psz_title )
671 vlc_meta_SetTitle( p_meta, p_sys->psz_title );
672 if( p_sys->psz_artist )
673 vlc_meta_SetArtist( p_meta, p_sys->psz_artist );
674 if( p_sys->psz_copyright )
675 vlc_meta_SetCopyright( p_meta, p_sys->psz_copyright );
676 if( p_sys->psz_description )
677 vlc_meta_SetDescription( p_meta, p_sys->psz_description );
689 /*****************************************************************************
691 *****************************************************************************/
692 static int HeaderRead( demux_t *p_demux )
694 demux_sys_t *p_sys = p_demux->p_sys;
695 uint8_t header[100]; /* FIXME */
704 /* Read the header */
705 if( stream_Read( p_demux->s, header, 10 ) < 10 )
709 i_id = VLC_FOURCC( header[0], header[1], header[2], header[3] );
710 i_size = GetDWBE( &header[4] );
711 i_version = GetWBE( &header[8] );
713 msg_Dbg( p_demux, "object %4.4s size=%d version=%d",
714 (char*)&i_id, i_size, i_version );
718 msg_Dbg( p_demux, "invalid size for object %4.4s", (char*)&i_id );
721 i_skip = i_size - 10;
723 if( i_id == VLC_FOURCC('.','R','M','F') )
725 if( stream_Read( p_demux->s, header, 8 ) < 8 ) return VLC_EGENERIC;
726 msg_Dbg( p_demux, " - file version=0x%x num headers=%d",
727 GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
731 else if( i_id == VLC_FOURCC('P','R','O','P') )
735 if( stream_Read(p_demux->s, header, 40) < 40 ) return VLC_EGENERIC;
737 msg_Dbg( p_demux, " - max bitrate=%d avg bitrate=%d",
738 GetDWBE(&header[0]), GetDWBE(&header[4]) );
739 msg_Dbg( p_demux, " - max packet size=%d avg bitrate=%d",
740 GetDWBE(&header[8]), GetDWBE(&header[12]) );
741 msg_Dbg( p_demux, " - packets count=%d", GetDWBE(&header[16]) );
742 msg_Dbg( p_demux, " - duration=%d ms", GetDWBE(&header[20]) );
743 msg_Dbg( p_demux, " - preroll=%d ms", GetDWBE(&header[24]) );
744 msg_Dbg( p_demux, " - index offset=%d", GetDWBE(&header[28]) );
745 msg_Dbg( p_demux, " - data offset=%d", GetDWBE(&header[32]) );
746 msg_Dbg( p_demux, " - num streams=%d", GetWBE(&header[36]) );
748 /* set the duration for export in control */
749 p_sys->i_our_duration = (int)GetDWBE(&header[20]);
751 i_flags = GetWBE(&header[38]);
752 msg_Dbg( p_demux, " - flags=0x%x %s%s%s",
754 i_flags&0x0001 ? "PN_SAVE_ENABLED " : "",
755 i_flags&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
756 i_flags&0x0004 ? "PN_LIVE_BROADCAST" : "" );
759 else if( i_id == VLC_FOURCC('C','O','N','T') )
764 /* FIXME FIXME: should convert from whatever the character
765 * encoding of the input meta data is to UTF-8. */
767 stream_Read( p_demux->s, header, 2 );
768 if( ( i_len = GetWBE( header ) ) > 0 )
770 psz = malloc( i_len + 1 );
771 stream_Read( p_demux->s, psz, i_len );
774 msg_Dbg( p_demux, " - title=`%s'", psz );
776 asprintf( &p_sys->psz_title, psz );
782 stream_Read( p_demux->s, header, 2 );
783 if( ( i_len = GetWBE( header ) ) > 0 )
785 psz = malloc( i_len + 1 );
786 stream_Read( p_demux->s, psz, i_len );
789 msg_Dbg( p_demux, " - author=`%s'", psz );
791 asprintf( &p_sys->psz_artist, psz );
797 stream_Read( p_demux->s, header, 2 );
798 if( ( i_len = GetWBE( header ) ) > 0 )
800 psz = malloc( i_len + 1 );
801 stream_Read( p_demux->s, psz, i_len );
804 msg_Dbg( p_demux, " - copyright=`%s'", psz );
806 asprintf( &p_sys->psz_copyright, psz );
812 stream_Read( p_demux->s, header, 2 );
813 if( ( i_len = GetWBE( header ) ) > 0 )
815 psz = malloc( i_len + 1 );
816 stream_Read( p_demux->s, psz, i_len );
819 msg_Dbg( p_demux, " - comment=`%s'", psz );
821 asprintf( &p_sys->psz_description, psz );
827 else if( i_id == VLC_FOURCC('M','D','P','R') )
829 /* Media properties header */
834 if( stream_Read(p_demux->s, header, 30) < 30 ) return VLC_EGENERIC;
835 i_num = GetWBE( header );
836 msg_Dbg( p_demux, " - id=0x%x", i_num );
837 msg_Dbg( p_demux, " - max bitrate=%d avg bitrate=%d",
838 GetDWBE(&header[2]), GetDWBE(&header[6]) );
839 msg_Dbg( p_demux, " - max packet size=%d avg packet size=%d",
840 GetDWBE(&header[10]), GetDWBE(&header[14]) );
841 msg_Dbg( p_demux, " - start time=%d", GetDWBE(&header[18]) );
842 msg_Dbg( p_demux, " - preroll=%d", GetDWBE(&header[22]) );
843 msg_Dbg( p_demux, " - duration=%d", GetDWBE(&header[26]) );
847 stream_Read( p_demux->s, header, 1 );
848 if( ( i_len = header[0] ) > 0 )
850 psz = malloc( i_len + 1 );
851 stream_Read( p_demux->s, psz, i_len );
854 msg_Dbg( p_demux, " - name=`%s'", psz );
860 stream_Read( p_demux->s, header, 1 );
861 if( ( i_len = header[0] ) > 0 )
863 psz = malloc( i_len + 1 );
864 stream_Read( p_demux->s, psz, i_len );
867 msg_Dbg( p_demux, " - mime=`%s'", psz );
873 stream_Read( p_demux->s, header, 4 );
874 if( ( i_len = GetDWBE( header ) ) > 0 )
876 ReadCodecSpecificData( p_demux, i_len, i_num );
877 stream_Read( p_demux->s, NULL, i_len );
883 else if( i_id == VLC_FOURCC('D','A','T','A') )
885 stream_Read( p_demux->s, header, 8 );
887 p_sys->i_data_offset = stream_Tell( p_demux->s ) - 10;
888 p_sys->i_data_size = i_size;
889 p_sys->i_data_packets_count = GetDWBE( header );
890 p_sys->i_data_packets = 0;
891 p_sys->i_data_offset_next = GetDWBE( &header[4] );
893 msg_Dbg( p_demux, " - packets count=%d next=%u",
894 p_sys->i_data_packets_count,
895 (uint32_t)p_sys->i_data_offset_next );
897 /* we have finished the header */
903 msg_Dbg( p_demux, "unknown chunk" );
906 if( i_skip < 0 ) return VLC_EGENERIC;
907 stream_Read( p_demux->s, NULL, i_skip );
910 /* TODO read index if possible */
915 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num )
917 demux_sys_t *p_sys = p_demux->p_sys;
922 msg_Dbg( p_demux, " - specific data len=%d", i_len );
923 if( stream_Peek(p_demux->s, &p_peek, i_len) < i_len ) return VLC_EGENERIC;
925 if( !strncmp( (char *)&p_peek[4], "VIDO", 4 ) )
927 es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( p_peek[8], p_peek[9],
928 p_peek[10], p_peek[11] ) );
929 fmt.video.i_width = GetWBE( &p_peek[12] );
930 fmt.video.i_height= GetWBE( &p_peek[14] );
933 fmt.p_extra = malloc( 8 );
934 ((uint32_t*)fmt.p_extra)[0] = GetDWBE( &p_peek[26] );
935 ((uint32_t*)fmt.p_extra)[1] = GetDWBE( &p_peek[30] );
937 msg_Dbg( p_demux, " - video 0x%08x 0x%08x",
938 ((uint32_t*)fmt.p_extra)[0], ((uint32_t*)fmt.p_extra)[1] );
940 if( GetDWBE( &p_peek[30] ) == 0x10003000 ||
941 GetDWBE( &p_peek[30] ) == 0x10003001 )
943 fmt.i_codec = VLC_FOURCC( 'R','V','1','3' );
945 else if( GetDWBE( &p_peek[30] ) == 0x20001000 ||
946 GetDWBE( &p_peek[30] ) == 0x20100001 ||
947 GetDWBE( &p_peek[30] ) == 0x20200002 )
949 fmt.i_codec = VLC_FOURCC( 'R','V','2','0' );
951 else if( GetDWBE( &p_peek[30] ) == 0x30202002 )
953 fmt.i_codec = VLC_FOURCC( 'R','V','3','0' );
955 else if( GetDWBE( &p_peek[30] ) == 0x40000000 )
957 fmt.i_codec = VLC_FOURCC( 'R','V','4','0' );
960 msg_Dbg( p_demux, " - video %4.4s %dx%d",
961 (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
963 tk = malloc( sizeof( real_track_t ) );
964 tk->i_out_subpacket = 0;
966 tk->i_subpackets = 0;
967 tk->p_subpackets = NULL;
972 tk->p_es = es_out_Add( p_demux->out, &fmt );
974 TAB_APPEND( p_sys->i_track, p_sys->track, tk );
976 else if( !strncmp( (char *)p_peek, ".ra\xfd", 4 ) )
978 int i_version = GetWBE( &p_peek[4] );
979 int i_header_size, i_flavor, i_coded_frame_size, i_subpacket_h;
980 int i_frame_size, i_subpacket_size;
982 msg_Dbg( p_demux, " - audio version=%d", i_version );
985 es_format_Init( &fmt, AUDIO_ES, 0 );
989 msg_Dbg( p_demux, " - audio version 3 is not supported!" );
993 p_peek += 2; /* 00 00 */
994 p_peek += 4; /* .ra4 or .ra5 */
995 p_peek += 4; /* ?? */
996 p_peek += 2; /* version (4 or 5) */
997 i_header_size = GetDWBE( p_peek ); p_peek += 4; /* header size */
998 i_flavor = GetWBE( p_peek ); p_peek += 2; /* codec flavor */
999 i_coded_frame_size = GetDWBE( p_peek ); p_peek += 4;
1000 p_peek += 4; /* ?? */
1001 p_peek += 4; /* ?? */
1002 p_peek += 4; /* ?? */
1003 i_subpacket_h = GetWBE( p_peek ); p_peek += 2;
1004 i_frame_size = GetWBE( p_peek ); p_peek += 2;
1005 i_subpacket_size = GetWBE( p_peek ); p_peek += 2;
1006 p_peek += 2; /* ?? */
1008 if( i_version == 5 ) p_peek += 6; /* 0, srate, 0 */
1010 fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2;
1011 p_peek += 2; /* ?? */
1012 fmt.audio.i_bitspersample = GetWBE( p_peek ); p_peek += 2;
1013 fmt.audio.i_channels = GetWBE( p_peek ); p_peek += 2;
1014 fmt.audio.i_blockalign = i_frame_size;
1016 if( i_version == 5 )
1018 p_peek += 4; /* genr */
1019 memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4;
1023 p_peek += p_peek[0] + 1; /* descr 1 */
1024 memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 ); /* descr 2 */
1025 p_peek += p_peek[0] + 1;
1028 msg_Dbg( p_demux, " - audio codec=%4.4s channels=%d rate=%dHz",
1029 (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate );
1031 p_peek += 3; /* ?? */
1032 if( i_version == 5 ) p_peek++;
1034 switch( fmt.i_codec )
1036 case VLC_FOURCC( 'd', 'n', 'e', 't' ):
1037 fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1040 case VLC_FOURCC( 'r', 'a', 'a', 'c' ):
1041 case VLC_FOURCC( 'r', 'a', 'c', 'p' ):
1042 fmt.i_extra = GetDWBE( p_peek ); p_peek += 4;
1043 if( fmt.i_extra > 0 ) { fmt.i_extra--; p_peek++; }
1044 if( fmt.i_extra > 0 )
1046 fmt.p_extra = malloc( fmt.i_extra );
1047 memcpy( fmt.p_extra, p_peek, fmt.i_extra );
1050 fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
1053 case VLC_FOURCC('c','o','o','k'):
1054 fmt.audio.i_blockalign = i_subpacket_size;
1055 if( !(fmt.i_extra = GetDWBE( p_peek )) ) break;
1056 fmt.p_extra = malloc( fmt.i_extra );
1057 memcpy( fmt.p_extra, p_peek + 4, fmt.i_extra );
1060 case VLC_FOURCC('2','8','_','8'):
1061 fmt.audio.i_blockalign = i_coded_frame_size;
1065 msg_Dbg( p_demux, " - unknown audio codec=%4.4s",
1066 (char*)&fmt.i_codec );
1070 if( fmt.i_codec != 0 )
1074 msg_Dbg( p_demux, " - extra data=%d", fmt.i_extra );
1076 tk = malloc( sizeof( real_track_t ) );
1082 tk->i_subpacket_h = i_subpacket_h;
1083 tk->i_subpacket_size = i_subpacket_size;
1084 tk->i_coded_frame_size = i_coded_frame_size;
1085 tk->i_frame_size = i_frame_size;
1087 tk->i_out_subpacket = 0;
1088 tk->i_subpacket = 0;
1089 tk->i_subpackets = 0;
1090 tk->p_subpackets = NULL;
1091 if( fmt.i_codec == VLC_FOURCC('c','o','o','k') )
1094 i_subpacket_h * i_frame_size / tk->i_subpacket_size;
1096 malloc( tk->i_subpackets * sizeof(block_t *) );
1098 else if( fmt.i_codec == VLC_FOURCC('2','8','_','8') )
1101 i_subpacket_h * i_frame_size / tk->i_coded_frame_size;
1103 malloc( tk->i_subpackets * sizeof(block_t *) );
1106 for( i = 0; i < tk->i_subpackets; i++ ) tk->p_subpackets[i] = NULL;
1108 tk->p_es = es_out_Add( p_demux->out, &fmt );
1110 TAB_APPEND( p_sys->i_track, p_sys->track, tk );