00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031
00032
00033
00034
00035 static int Open ( vlc_object_t * );
00036 static void Close ( vlc_object_t * );
00037
00038 vlc_module_begin();
00039 set_description( _("Real demuxer" ) );
00040 set_capability( "demux2", 15 );
00041 set_category( CAT_INPUT );
00042 set_subcategory( SUBCAT_INPUT_DEMUX );
00043 set_callbacks( Open, Close );
00044 add_shortcut( "real" );
00045 add_shortcut( "rm" );
00046 vlc_module_end();
00047
00048
00049
00050
00051
00052 typedef struct
00053 {
00054 int i_id;
00055 es_format_t fmt;
00056
00057 es_out_id_t *p_es;
00058
00059 int i_frame;
00060 block_t *p_frame;
00061
00062 int i_subpacket_h;
00063 int i_subpacket_size;
00064 int i_coded_frame_size;
00065 int i_frame_size;
00066
00067 int i_subpacket;
00068 int i_subpackets;
00069 block_t **p_subpackets;
00070 int i_out_subpacket;
00071
00072 } real_track_t;
00073
00074 struct demux_sys_t
00075 {
00076 int64_t i_data_offset;
00077 int64_t i_data_size;
00078 uint32_t i_data_packets_count;
00079 uint32_t i_data_packets;
00080 int64_t i_data_offset_next;
00081
00082 int i_track;
00083 real_track_t **track;
00084
00085 uint8_t buffer[65536];
00086
00087 int64_t i_pcr;
00088 };
00089
00090 static int Demux( demux_t *p_demux );
00091 static int Control( demux_t *p_demux, int i_query, va_list args );
00092
00093 static int HeaderRead( demux_t *p_demux );
00094 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num );
00095
00096
00097
00098
00099 static int Open( vlc_object_t *p_this )
00100 {
00101 demux_t *p_demux = (demux_t*)p_this;
00102 demux_sys_t *p_sys;
00103
00104 uint8_t *p_peek;
00105
00106 if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) return VLC_EGENERIC;
00107 if( strncmp( (char *)p_peek, ".RMF", 4 ) ) return VLC_EGENERIC;
00108
00109
00110 p_demux->pf_demux = Demux;
00111 p_demux->pf_control = Control;
00112 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00113 memset( p_sys, 0, sizeof( demux_sys_t ) );
00114 p_sys->i_data_offset = 0;
00115 p_sys->i_track = 0;
00116 p_sys->track = NULL;
00117 p_sys->i_pcr = 1;
00118
00119
00120
00121 if( HeaderRead( p_demux ) )
00122 {
00123 int i;
00124 msg_Err( p_demux, "invalid header" );
00125 for( i = 0; i < p_sys->i_track; i++ )
00126 {
00127 real_track_t *tk = p_sys->track[i];
00128
00129 if( tk->p_es )
00130 {
00131 es_out_Del( p_demux->out, tk->p_es );
00132 }
00133 free( tk );
00134 }
00135 if( p_sys->i_track > 0 )
00136 {
00137 free( p_sys->track );
00138 }
00139 free( p_sys );
00140 return VLC_EGENERIC;
00141 }
00142
00143 return VLC_SUCCESS;
00144 }
00145
00146
00147
00148
00149 static void Close( vlc_object_t *p_this )
00150 {
00151 demux_t *p_demux = (demux_t*)p_this;
00152 demux_sys_t *p_sys = p_demux->p_sys;
00153 int i;
00154
00155 for( i = 0; i < p_sys->i_track; i++ )
00156 {
00157 real_track_t *tk = p_sys->track[i];
00158
00159 if( tk->p_frame ) block_Release( tk->p_frame );
00160 es_format_Clean( &tk->fmt );
00161
00162 while( tk->i_subpackets-- )
00163 {
00164 if( tk->p_subpackets[tk->i_subpackets] )
00165 block_Release( tk->p_subpackets[tk->i_subpackets] );
00166 if( !tk->i_subpackets ) free( tk->p_subpackets );
00167 }
00168
00169 free( tk );
00170 }
00171
00172 if( p_sys->i_track > 0 ) free( p_sys->track );
00173 free( p_sys );
00174 }
00175
00176
00177
00178
00179
00180 static int Demux( demux_t *p_demux )
00181 {
00182 demux_sys_t *p_sys = p_demux->p_sys;
00183 uint8_t header[18];
00184 int i_size, i_id, i_flags, i;
00185 int64_t i_pts;
00186 real_track_t *tk = NULL;
00187 vlc_bool_t b_selected;
00188
00189 if( p_sys->i_data_packets >= p_sys->i_data_packets_count &&
00190 p_sys->i_data_packets_count )
00191 {
00192 if( stream_Read( p_demux->s, header, 18 ) < 18 )
00193 {
00194 return 0;
00195 }
00196 if( strncmp( (char *)header, "DATA", 4 ) )
00197 {
00198 return 0;
00199 }
00200 p_sys->i_data_offset = stream_Tell( p_demux->s ) - 18;
00201 p_sys->i_data_size = GetDWBE( &header[4] );
00202 p_sys->i_data_packets_count = GetDWBE( &header[10] );
00203 p_sys->i_data_packets = 0;
00204 p_sys->i_data_offset_next = GetDWBE( &header[14] );
00205
00206 msg_Dbg( p_demux, "entering new DATA packets=%d next=%u",
00207 p_sys->i_data_packets_count,
00208 (uint32_t)p_sys->i_data_offset_next );
00209 }
00210
00211 if( stream_Read( p_demux->s, header, 12 ) < 12 ) return 0;
00212
00213 i_size = GetWBE( &header[2] ) - 12;
00214 i_id = GetWBE( &header[4] );
00215 i_pts = 1000 * GetDWBE( &header[6] );
00216 i_pts += 1000;
00217 i_flags= header[11];
00218
00219 #if 0
00220 msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u",
00221 p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) );
00222 #endif
00223
00224 p_sys->i_data_packets++;
00225
00226 stream_Read( p_demux->s, p_sys->buffer, i_size );
00227
00228 for( i = 0; i < p_sys->i_track; i++ )
00229 {
00230 if( p_sys->track[i]->i_id == i_id ) tk = p_sys->track[i];
00231 }
00232
00233 if( tk == NULL )
00234 {
00235 msg_Warn( p_demux, "unknown track id(0x%x)", i_id );
00236 return 1;
00237 }
00238 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b_selected );
00239
00240 if( tk->fmt.i_cat == VIDEO_ES && b_selected )
00241 {
00242 uint8_t *p = p_sys->buffer;
00243
00244 while( p < &p_sys->buffer[i_size - 2] )
00245 {
00246 uint8_t h = *p++;
00247 int i_len = 0;
00248 int i_copy;
00249 int i_subseq = 0;
00250 int i_seqnum = 0;
00251 int i_offset = 0;
00252
00253 if( (h&0xc0) == 0x40 )
00254 {
00255
00256 p++;
00257 i_len = &p_sys->buffer[i_size] - p;
00258 }
00259 else
00260 {
00261 if( (h&0x40) == 0 )
00262 {
00263 i_subseq = (*p++)&0x7f;
00264 }
00265 i_len = (p[0] << 8)|p[1]; p += 2;
00266 if( (i_len&0xc000) == 0 )
00267 {
00268 i_len <<= 16;
00269 i_len |= (p[0] << 8)|p[1]; p += 2;
00270 i_len &= 0x3fffffff;
00271 }
00272 else
00273 {
00274 i_len &= 0x3fff;
00275 }
00276
00277 i_offset = (p[0] << 8)|p[1]; p += 2;
00278 if( (i_offset&0xc000) == 0 )
00279 {
00280 i_offset <<= 16;
00281 i_offset |= (p[0] << 8)|p[1]; p += 2;
00282 i_offset &= 0x3fffffff;
00283 }
00284 else
00285 {
00286 i_offset &= 0x3fff;
00287 }
00288 i_seqnum = *p++;
00289 }
00290
00291 i_copy = i_len - i_offset;
00292 if( i_copy > &p_sys->buffer[i_size] - p )
00293 {
00294 i_copy = &p_sys->buffer[i_size] - p;
00295 }
00296 else if( i_copy < 0 )
00297 {
00298 break;
00299 }
00300
00301 msg_Dbg( p_demux, " - len=%d offset=%d size=%d subseq=%d seqnum=%d",
00302 i_len, i_offset, i_copy, i_subseq, i_seqnum );
00303
00304 if( (h&0xc0) == 0x80 )
00305 {
00306
00307 i_copy = i_offset;
00308 i_offset = i_len - i_copy;
00309 msg_Dbg( p_demux, "last fixing copy=%d offset=%d",
00310 i_copy, i_offset );
00311 }
00312
00313 if( tk->p_frame &&
00314 ( tk->p_frame->i_dts != i_pts ||
00315 tk->i_frame != i_len ) )
00316 {
00317 msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer );
00318
00319 if( p_sys->i_pcr < tk->p_frame->i_dts )
00320 {
00321 p_sys->i_pcr = tk->p_frame->i_dts;
00322
00323 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00324 (int64_t)p_sys->i_pcr );
00325 }
00326 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
00327
00328 tk->i_frame = 0;
00329 tk->p_frame = NULL;
00330 }
00331
00332 if( (h&0xc0) != 0x80 && (h&0xc0) != 0x00 && !tk->p_frame )
00333 {
00334
00335 i_len = i_copy;
00336 i_offset = 0;
00337 }
00338
00339
00340 if( tk->p_frame == NULL )
00341 {
00342 msg_Dbg( p_demux, "new frame size=%d", i_len );
00343 tk->i_frame = i_len;
00344 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
00345 {
00346 return -1;
00347 }
00348 memset( &tk->p_frame->p_buffer[8], 0, i_len );
00349 tk->p_frame->i_dts = i_pts;
00350 tk->p_frame->i_pts = i_pts;
00351
00352 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;
00353 ((uint32_t*)tk->p_frame->p_buffer)[1] = 0;
00354 }
00355
00356 if( i_offset < tk->i_frame)
00357 {
00358 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
00359
00360 msg_Dbg( p_demux, "copying new buffer n=%d offset=%d copy=%d",
00361 i_ck, i_offset, i_copy );
00362
00363 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00364
00365 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00366 }
00367
00368 p += i_copy;
00369
00370 if( (h&0xc0) != 0x80 )
00371 {
00372 break;
00373 }
00374
00375 #if 0
00376 if( tk->p_frame )
00377 {
00378
00379 int i_ck = ((uint32_t*)tk->p_frame->p_buffer)[1]++;
00380
00381 if( (h&0xc0) == 0x80 )
00382 {
00383
00384 i_copy = i_offset;
00385 i_offset = i_len - i_offset;
00386
00387 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00388 memcpy( &tk->p_frame->p_buffer[i_offset+ 8], p, i_copy );
00389 p += i_copy;
00390
00391 if( p_sys->i_pcr < tk->p_frame->i_dts )
00392 {
00393 p_sys->i_pcr = tk->p_frame->i_dts;
00394 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00395 (int64_t)p_sys->i_pcr );
00396 }
00397 es_out_Send( p_demux->out, tk->p_es, tk->p_frame );
00398
00399 tk->i_frame = 0;
00400 tk->p_frame = NULL;
00401
00402 continue;
00403 }
00404
00405 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[i_ck] = i_offset;
00406 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00407 break;
00408 }
00409
00410 if( (h&0xc0) != 0x00 )
00411 {
00412 block_t *p_frame;
00413
00414
00415 if( !( p_frame = block_New( p_demux, i_copy + 8 + 8 ) ) )
00416 {
00417 return -1;
00418 }
00419 p_frame->i_dts = i_pts;
00420 p_frame->i_pts = i_pts;
00421
00422 ((uint32_t*)p_frame->p_buffer)[0] = i_copy;
00423 ((uint32_t*)p_frame->p_buffer)[1] = 1;
00424 ((uint32_t*)(p_frame->p_buffer+i_copy+8))[0] = 0;
00425 memcpy( &p_frame->p_buffer[8], p, i_copy );
00426
00427 p += i_copy;
00428
00429 if( p_sys->i_pcr < p_frame->i_dts )
00430 {
00431 p_sys->i_pcr = p_frame->i_dts;
00432 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00433 (int64_t)p_sys->i_pcr );
00434 }
00435 es_out_Send( p_demux->out, tk->p_es, p_frame );
00436 }
00437 else
00438 {
00439
00440 tk->i_frame = i_len;
00441 if( !( tk->p_frame = block_New( p_demux, i_len + 8 + 1000) ) )
00442 {
00443 return -1;
00444 }
00445 memset( &tk->p_frame->p_buffer[8], 0, i_len );
00446 tk->p_frame->i_dts = i_pts;
00447 tk->p_frame->i_pts = i_pts;
00448
00449 ((uint32_t*)tk->p_frame->p_buffer)[0] = i_len;
00450 ((uint32_t*)tk->p_frame->p_buffer)[1] = 1;
00451 ((uint32_t*)(tk->p_frame->p_buffer+i_len+8))[0] = i_offset;
00452 memcpy( &tk->p_frame->p_buffer[i_offset + 8], p, i_copy );
00453
00454 break;
00455 }
00456 #endif
00457 }
00458 }
00459 else if( tk->fmt.i_cat == AUDIO_ES && b_selected )
00460 {
00461
00462 if( p_sys->i_pcr < i_pts )
00463 {
00464 p_sys->i_pcr = i_pts;
00465 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00466 (int64_t)p_sys->i_pcr );
00467 }
00468
00469 if( tk->fmt.i_codec == VLC_FOURCC( 'm', 'p', '4', 'a' ) )
00470 {
00471 int i_sub = (p_sys->buffer[1] >> 4)&0x0f;
00472 uint8_t *p_sub = &p_sys->buffer[2+2*i_sub];
00473
00474 int i;
00475 for( i = 0; i < i_sub; i++ )
00476 {
00477 int i_sub_size = GetWBE( &p_sys->buffer[2+i*2]);
00478 block_t *p_block = block_New( p_demux, i_sub_size );
00479 if( p_block )
00480 {
00481 memcpy( p_block->p_buffer, p_sub, i_sub_size );
00482 p_sub += i_sub_size;
00483
00484 p_block->i_dts =
00485 p_block->i_pts = ( i == 0 ? i_pts : 0 );
00486
00487 es_out_Send( p_demux->out, tk->p_es, p_block );
00488 }
00489 }
00490 }
00491 else if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) ||
00492 tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
00493 {
00494 uint8_t *p_buf = p_sys->buffer;
00495 int y = tk->i_subpacket / (tk->i_frame_size /tk->i_subpacket_size);
00496 int i_index, i;
00497
00498
00499 if( i_flags & 2 ) y = tk->i_subpacket = 0;
00500
00501 if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) )
00502 for( i = 0; i < tk->i_frame_size / tk->i_subpacket_size; i++ )
00503 {
00504 block_t *p_block = block_New( p_demux, tk->i_subpacket_size );
00505 memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size );
00506 p_buf += tk->i_subpacket_size;
00507
00508 i_index = tk->i_subpacket_h * i +
00509 ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1);
00510
00511 p_block->i_dts = p_block->i_pts = i_pts;
00512 tk->p_subpackets[i_index] = p_block;
00513 tk->i_subpacket++;
00514 }
00515
00516 if( tk->fmt.i_codec == VLC_FOURCC('2','8','_','8') )
00517 for( i = 0; i < tk->i_subpacket_h / 2; i++ )
00518 {
00519 block_t *p_block = block_New( p_demux, tk->i_coded_frame_size);
00520 memcpy( p_block->p_buffer, p_buf, tk->i_coded_frame_size );
00521 p_buf += tk->i_coded_frame_size;
00522
00523 i_index = (i * 2 * tk->i_frame_size) /
00524 tk->i_coded_frame_size + y;
00525
00526 p_block->i_dts = p_block->i_pts = i_pts;
00527 tk->p_subpackets[i_index] = p_block;
00528 tk->i_subpacket++;
00529 }
00530
00531 while( tk->i_out_subpacket != tk->i_subpackets &&
00532 tk->p_subpackets[tk->i_out_subpacket] )
00533 {
00534 block_t *p_block = tk->p_subpackets[tk->i_out_subpacket];
00535 tk->p_subpackets[tk->i_out_subpacket] = 0;
00536
00537 if( tk->i_out_subpacket ) p_block->i_dts = p_block->i_pts = 0;
00538 es_out_Send( p_demux->out, tk->p_es, p_block );
00539
00540 tk->i_out_subpacket++;
00541 }
00542
00543 if( tk->i_subpacket == tk->i_subpackets &&
00544 tk->i_out_subpacket != tk->i_subpackets )
00545 {
00546 msg_Warn( p_demux, "i_subpacket != i_out_subpacket, "
00547 "this shouldn't happen" );
00548 }
00549
00550 if( tk->i_subpacket == tk->i_subpackets )
00551 {
00552 tk->i_subpacket = 0;
00553 tk->i_out_subpacket = 0;
00554 }
00555 }
00556 else
00557 {
00558 block_t *p_block = block_New( p_demux, i_size );
00559
00560 if( tk->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', ' ' ) )
00561 {
00562 uint8_t *src = p_sys->buffer;
00563 uint8_t *dst = p_block->p_buffer;
00564
00565
00566 while( dst < &p_block->p_buffer[i_size- 1])
00567 {
00568 *dst++ = src[1];
00569 *dst++ = src[0];
00570
00571 src += 2;
00572 }
00573 }
00574 else
00575 {
00576 memcpy( p_block->p_buffer, p_sys->buffer, i_size );
00577 }
00578 p_block->i_dts = p_block->i_pts = i_pts;
00579 es_out_Send( p_demux->out, tk->p_es, p_block );
00580 }
00581 }
00582
00583
00584 return 1;
00585 }
00586
00587
00588
00589
00590 static int Control( demux_t *p_demux, int i_query, va_list args )
00591 {
00592 #if 0
00593 demux_sys_t *p_sys = p_demux->p_sys;
00594 double f, *pf;
00595 int64_t i64, *pi64;
00596
00597 switch( i_query )
00598 {
00599 case DEMUX_GET_POSITION:
00600 pf = (double*) va_arg( args, double* );
00601 i64 = stream_Size( p_demux->s );
00602 if( i64 > 0 )
00603 {
00604 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
00605 }
00606 else
00607 {
00608 *pf = 0.0;
00609 }
00610 return VLC_SUCCESS;
00611 case DEMUX_SET_POSITION:
00612 f = (double) va_arg( args, double );
00613 i64 = stream_Size( p_demux->s );
00614
00615 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00616
00617 return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
00618
00619 case DEMUX_GET_TIME:
00620 pi64 = (int64_t*)va_arg( args, int64_t * );
00621 if( p_sys->i_mux_rate > 0 )
00622 {
00623 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
00624 return VLC_SUCCESS;
00625 }
00626 *pi64 = 0;
00627 return VLC_EGENERIC;
00628
00629 case DEMUX_GET_LENGTH:
00630 pi64 = (int64_t*)va_arg( args, int64_t * );
00631 if( p_sys->i_mux_rate > 0 )
00632 {
00633 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
00634 return VLC_SUCCESS;
00635 }
00636 *pi64 = 0;
00637 return VLC_EGENERIC;
00638
00639 case DEMUX_SET_TIME:
00640 case DEMUX_GET_FPS:
00641 default:
00642 return VLC_EGENERIC;
00643 }
00644 #endif
00645 return VLC_EGENERIC;
00646 }
00647
00648
00649
00650
00651 static int HeaderRead( demux_t *p_demux )
00652 {
00653 demux_sys_t *p_sys = p_demux->p_sys;
00654 uint8_t header[100];
00655
00656 uint32_t i_id;
00657 uint32_t i_size;
00658 int64_t i_skip;
00659 int i_version;
00660
00661 for( ;; )
00662 {
00663
00664 if( stream_Read( p_demux->s, header, 10 ) < 10 )
00665 {
00666 return VLC_EGENERIC;
00667 }
00668 i_id = VLC_FOURCC( header[0], header[1], header[2], header[3] );
00669 i_size = GetDWBE( &header[4] );
00670 i_version = GetWBE( &header[8] );
00671
00672 msg_Dbg( p_demux, "object %4.4s size=%d version=%d",
00673 (char*)&i_id, i_size, i_version );
00674
00675 if( i_size < 10 )
00676 {
00677 msg_Dbg( p_demux, "invalid size for object %4.4s", (char*)&i_id );
00678 return VLC_EGENERIC;
00679 }
00680 i_skip = i_size - 10;
00681
00682 if( i_id == VLC_FOURCC('.','R','M','F') )
00683 {
00684 if( stream_Read( p_demux->s, header, 8 ) < 8 ) return VLC_EGENERIC;
00685 msg_Dbg( p_demux, " - file version=0x%x num headers=%d",
00686 GetDWBE( &header[0] ), GetDWBE( &header[4] ) );
00687
00688 i_skip -= 8;
00689 }
00690 else if( i_id == VLC_FOURCC('P','R','O','P') )
00691 {
00692 int i_flags;
00693
00694 if( stream_Read(p_demux->s, header, 40) < 40 ) return VLC_EGENERIC;
00695
00696 msg_Dbg( p_demux, " - max bitrate=%d avg bitrate=%d",
00697 GetDWBE(&header[0]), GetDWBE(&header[4]) );
00698 msg_Dbg( p_demux, " - max packet size=%d avg bitrate=%d",
00699 GetDWBE(&header[8]), GetDWBE(&header[12]) );
00700 msg_Dbg( p_demux, " - packets count=%d", GetDWBE(&header[16]) );
00701 msg_Dbg( p_demux, " - duration=%d ms", GetDWBE(&header[20]) );
00702 msg_Dbg( p_demux, " - preroll=%d ms", GetDWBE(&header[24]) );
00703 msg_Dbg( p_demux, " - index offset=%d", GetDWBE(&header[28]) );
00704 msg_Dbg( p_demux, " - data offset=%d", GetDWBE(&header[32]) );
00705 msg_Dbg( p_demux, " - num streams=%d", GetWBE(&header[36]) );
00706 i_flags = GetWBE(&header[38]);
00707 msg_Dbg( p_demux, " - flags=0x%x %s%s%s",
00708 i_flags,
00709 i_flags&0x0001 ? "PN_SAVE_ENABLED " : "",
00710 i_flags&0x0002 ? "PN_PERFECT_PLAY_ENABLED " : "",
00711 i_flags&0x0004 ? "PN_LIVE_BROADCAST" : "" );
00712 i_skip -= 40;
00713 }
00714 else if( i_id == VLC_FOURCC('C','O','N','T') )
00715 {
00716 int i_len;
00717 char *psz;
00718
00719 stream_Read( p_demux->s, header, 2 );
00720 if( ( i_len = GetWBE( header ) ) > 0 )
00721 {
00722 psz = malloc( i_len + 1 );
00723 stream_Read( p_demux->s, psz, i_len );
00724 psz[i_len] = '\0';
00725
00726 msg_Dbg( p_demux, " - title=`%s'", psz );
00727 free( psz );
00728 i_skip -= i_len;
00729 }
00730 i_skip -= 2;
00731
00732 stream_Read( p_demux->s, header, 2 );
00733 if( ( i_len = GetWBE( header ) ) > 0 )
00734 {
00735 psz = malloc( i_len + 1 );
00736 stream_Read( p_demux->s, psz, i_len );
00737 psz[i_len] = '\0';
00738
00739 msg_Dbg( p_demux, " - author=`%s'", psz );
00740 free( psz );
00741 i_skip -= i_len;
00742 }
00743 i_skip -= 2;
00744
00745 stream_Read( p_demux->s, header, 2 );
00746 if( ( i_len = GetWBE( header ) ) > 0 )
00747 {
00748 psz = malloc( i_len + 1 );
00749 stream_Read( p_demux->s, psz, i_len );
00750 psz[i_len] = '\0';
00751
00752 msg_Dbg( p_demux, " - copyright=`%s'", psz );
00753 free( psz );
00754 i_skip -= i_len;
00755 }
00756 i_skip -= 2;
00757
00758 stream_Read( p_demux->s, header, 2 );
00759 if( ( i_len = GetWBE( header ) ) > 0 )
00760 {
00761 psz = malloc( i_len + 1 );
00762 stream_Read( p_demux->s, psz, i_len );
00763 psz[i_len] = '\0';
00764
00765 msg_Dbg( p_demux, " - comment=`%s'", psz );
00766 free( psz );
00767 i_skip -= i_len;
00768 }
00769 i_skip -= 2;
00770 }
00771 else if( i_id == VLC_FOURCC('M','D','P','R') )
00772 {
00773
00774 int i_num;
00775 int i_len;
00776 char *psz;
00777
00778 if( stream_Read(p_demux->s, header, 30) < 30 ) return VLC_EGENERIC;
00779 i_num = GetWBE( header );
00780 msg_Dbg( p_demux, " - id=0x%x", i_num );
00781 msg_Dbg( p_demux, " - max bitrate=%d avg bitrate=%d",
00782 GetDWBE(&header[2]), GetDWBE(&header[6]) );
00783 msg_Dbg( p_demux, " - max packet size=%d avg packet size=%d",
00784 GetDWBE(&header[10]), GetDWBE(&header[14]) );
00785 msg_Dbg( p_demux, " - start time=%d", GetDWBE(&header[18]) );
00786 msg_Dbg( p_demux, " - preroll=%d", GetDWBE(&header[22]) );
00787 msg_Dbg( p_demux, " - duration=%d", GetDWBE(&header[26]) );
00788 i_skip -= 30;
00789
00790 stream_Read( p_demux->s, header, 1 );
00791 if( ( i_len = header[0] ) > 0 )
00792 {
00793 psz = malloc( i_len + 1 );
00794 stream_Read( p_demux->s, psz, i_len );
00795 psz[i_len] = '\0';
00796
00797 msg_Dbg( p_demux, " - name=`%s'", psz );
00798 free( psz );
00799 i_skip -= i_len;
00800 }
00801 i_skip--;
00802
00803 stream_Read( p_demux->s, header, 1 );
00804 if( ( i_len = header[0] ) > 0 )
00805 {
00806 psz = malloc( i_len + 1 );
00807 stream_Read( p_demux->s, psz, i_len );
00808 psz[i_len] = '\0';
00809
00810 msg_Dbg( p_demux, " - mime=`%s'", psz );
00811 free( psz );
00812 i_skip -= i_len;
00813 }
00814 i_skip--;
00815
00816 stream_Read( p_demux->s, header, 4 );
00817 if( ( i_len = GetDWBE( header ) ) > 0 )
00818 {
00819 ReadCodecSpecificData( p_demux, i_len, i_num );
00820 stream_Read( p_demux->s, NULL, i_len );
00821
00822 i_skip -= i_len;
00823 }
00824 i_skip -= 4;
00825 }
00826 else if( i_id == VLC_FOURCC('D','A','T','A') )
00827 {
00828 stream_Read( p_demux->s, header, 8 );
00829
00830 p_sys->i_data_offset = stream_Tell( p_demux->s ) - 10;
00831 p_sys->i_data_size = i_size;
00832 p_sys->i_data_packets_count = GetDWBE( header );
00833 p_sys->i_data_packets = 0;
00834 p_sys->i_data_offset_next = GetDWBE( &header[4] );
00835
00836 msg_Dbg( p_demux, " - packets count=%d next=%u",
00837 p_sys->i_data_packets_count,
00838 (uint32_t)p_sys->i_data_offset_next );
00839
00840
00841 break;
00842 }
00843 else
00844 {
00845
00846 msg_Dbg( p_demux, "unknown chunk" );
00847 }
00848
00849 if( i_skip < 0 ) return VLC_EGENERIC;
00850 stream_Read( p_demux->s, NULL, i_skip );
00851 }
00852
00853
00854
00855 return VLC_SUCCESS;
00856 }
00857
00858 static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num )
00859 {
00860 demux_sys_t *p_sys = p_demux->p_sys;
00861 es_format_t fmt;
00862 real_track_t *tk;
00863 uint8_t *p_peek;
00864
00865 msg_Dbg( p_demux, " - specific data len=%d", i_len );
00866 if( stream_Peek(p_demux->s, &p_peek, i_len) < i_len ) return VLC_EGENERIC;
00867
00868 if( !strncmp( (char *)&p_peek[4], "VIDO", 4 ) )
00869 {
00870 es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( p_peek[8], p_peek[9],
00871 p_peek[10], p_peek[11] ) );
00872 fmt.video.i_width = GetWBE( &p_peek[12] );
00873 fmt.video.i_height= GetWBE( &p_peek[14] );
00874
00875 fmt.i_extra = 8;
00876 fmt.p_extra = malloc( 8 );
00877 ((uint32_t*)fmt.p_extra)[0] = GetDWBE( &p_peek[26] );
00878 ((uint32_t*)fmt.p_extra)[1] = GetDWBE( &p_peek[30] );
00879
00880 msg_Dbg( p_demux, " - video 0x%08x 0x%08x",
00881 ((uint32_t*)fmt.p_extra)[0], ((uint32_t*)fmt.p_extra)[1] );
00882
00883 if( GetDWBE( &p_peek[30] ) == 0x10003000 ||
00884 GetDWBE( &p_peek[30] ) == 0x10003001 )
00885 {
00886 fmt.i_codec = VLC_FOURCC( 'R','V','1','3' );
00887 }
00888
00889 msg_Dbg( p_demux, " - video %4.4s %dx%d",
00890 (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
00891
00892 tk = malloc( sizeof( real_track_t ) );
00893 tk->i_id = i_num;
00894 tk->fmt = fmt;
00895 tk->i_frame = 0;
00896 tk->p_frame = NULL;
00897 tk->p_es = es_out_Add( p_demux->out, &fmt );
00898
00899 TAB_APPEND( p_sys->i_track, p_sys->track, tk );
00900 }
00901 else if( !strncmp( (char *)p_peek, ".ra\xfd", 4 ) )
00902 {
00903 int i_version = GetWBE( &p_peek[4] );
00904 int i_header_size, i_flavor, i_coded_frame_size, i_subpacket_h;
00905 int i_frame_size, i_subpacket_size;
00906
00907 msg_Dbg( p_demux, " - audio version=%d", i_version );
00908
00909 p_peek += 6;
00910 es_format_Init( &fmt, AUDIO_ES, 0 );
00911
00912 if( i_version == 3 )
00913 {
00914 msg_Dbg( p_demux, " - audio version 3 is not supported!" );
00915 return VLC_EGENERIC;
00916 }
00917
00918 p_peek += 2;
00919 p_peek += 4;
00920 p_peek += 4;
00921 p_peek += 2;
00922 i_header_size = GetDWBE( p_peek ); p_peek += 4;
00923 i_flavor = GetWBE( p_peek ); p_peek += 2;
00924 i_coded_frame_size = GetDWBE( p_peek ); p_peek += 4;
00925 p_peek += 4;
00926 p_peek += 4;
00927 p_peek += 4;
00928 i_subpacket_h = GetWBE( p_peek ); p_peek += 2;
00929 i_frame_size = GetWBE( p_peek ); p_peek += 2;
00930 i_subpacket_size = GetWBE( p_peek ); p_peek += 2;
00931 p_peek += 2;
00932
00933 if( i_version == 5 ) p_peek += 6;
00934
00935 fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2;
00936 p_peek += 2;
00937 fmt.audio.i_bitspersample = GetWBE( p_peek ); p_peek += 2;
00938 fmt.audio.i_channels = GetWBE( p_peek ); p_peek += 2;
00939 fmt.audio.i_blockalign = i_frame_size;
00940
00941 if( i_version == 5 )
00942 {
00943 p_peek += 4;
00944 memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4;
00945 }
00946 else
00947 {
00948 p_peek += p_peek[0] + 1;
00949 memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 );
00950 p_peek += p_peek[0] + 1;
00951 }
00952
00953 msg_Dbg( p_demux, " - audio codec=%4.4s channels=%d rate=%dHz",
00954 (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate );
00955
00956 p_peek += 3;
00957 if( i_version == 5 ) p_peek++;
00958
00959 switch( fmt.i_codec )
00960 {
00961 case VLC_FOURCC( 'd', 'n', 'e', 't' ):
00962 fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
00963 break;
00964
00965 case VLC_FOURCC( 'r', 'a', 'a', 'c' ):
00966 case VLC_FOURCC( 'r', 'a', 'c', 'p' ):
00967 fmt.i_extra = GetDWBE( p_peek ); p_peek += 4;
00968 if( fmt.i_extra > 0 ) { fmt.i_extra--; p_peek++; }
00969 if( fmt.i_extra > 0 )
00970 {
00971 fmt.p_extra = malloc( fmt.i_extra );
00972 memcpy( fmt.p_extra, p_peek, fmt.i_extra );
00973 }
00974
00975 fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
00976 break;
00977
00978 case VLC_FOURCC('c','o','o','k'):
00979 fmt.audio.i_blockalign = i_subpacket_size;
00980 if( !(fmt.i_extra = GetDWBE( p_peek )) ) break;
00981 fmt.p_extra = malloc( fmt.i_extra );
00982 memcpy( fmt.p_extra, p_peek + 4, fmt.i_extra );
00983 break;
00984
00985 case VLC_FOURCC('2','8','_','8'):
00986 fmt.audio.i_blockalign = i_coded_frame_size;
00987 break;
00988
00989 default:
00990 msg_Dbg( p_demux, " - unknown audio codec=%4.4s",
00991 (char*)&fmt.i_codec );
00992 break;
00993 }
00994
00995 if( fmt.i_codec != 0 )
00996 {
00997 int i;
00998
00999 msg_Dbg( p_demux, " - extra data=%d", fmt.i_extra );
01000
01001 tk = malloc( sizeof( real_track_t ) );
01002 tk->i_id = i_num;
01003 tk->fmt = fmt;
01004 tk->i_frame = 0;
01005 tk->p_frame = NULL;
01006
01007 tk->i_subpacket_h = i_subpacket_h;
01008 tk->i_subpacket_size = i_subpacket_size;
01009 tk->i_coded_frame_size = i_coded_frame_size;
01010 tk->i_frame_size = i_frame_size;
01011
01012 tk->i_out_subpacket = 0;
01013 tk->i_subpacket = 0;
01014 tk->i_subpackets = 0;
01015 tk->p_subpackets = NULL;
01016 if( fmt.i_codec == VLC_FOURCC('c','o','o','k') )
01017 {
01018 tk->i_subpackets =
01019 i_subpacket_h * i_frame_size / tk->i_subpacket_size;
01020 tk->p_subpackets =
01021 malloc( tk->i_subpackets * sizeof(block_t *) );
01022 }
01023 else if( fmt.i_codec == VLC_FOURCC('2','8','_','8') )
01024 {
01025 tk->i_subpackets =
01026 i_subpacket_h * i_frame_size / tk->i_coded_frame_size;
01027 tk->p_subpackets =
01028 malloc( tk->i_subpackets * sizeof(block_t *) );
01029 }
01030
01031 for( i = 0; i < tk->i_subpackets; i++ ) tk->p_subpackets[i] = NULL;
01032
01033 tk->p_es = es_out_Add( p_demux->out, &fmt );
01034
01035 TAB_APPEND( p_sys->i_track, p_sys->track, tk );
01036 }
01037 }
01038
01039 return VLC_SUCCESS;
01040 }