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
00036
00037
00038
00039
00040
00041 static int Open ( vlc_object_t * );
00042 static void Close ( vlc_object_t * );
00043
00044 vlc_module_begin();
00045 set_description( _("NullSoft demuxer" ) );
00046 set_capability( "demux2", 10 );
00047 set_category( CAT_INPUT );
00048 set_subcategory( SUBCAT_INPUT_DEMUX );
00049 set_callbacks( Open, Close );
00050 add_shortcut( "nsv" );
00051 vlc_module_end();
00052
00053
00054
00055
00056
00057 struct demux_sys_t
00058 {
00059 es_format_t fmt_audio;
00060 es_out_id_t *p_audio;
00061
00062 es_format_t fmt_video;
00063 es_out_id_t *p_video;
00064
00065 es_format_t fmt_sub;
00066 es_out_id_t *p_sub;
00067
00068 int64_t i_pcr;
00069 int64_t i_time;
00070 int64_t i_pcr_inc;
00071 };
00072
00073 static int Demux ( demux_t *p_demux );
00074 static int Control( demux_t *p_demux, int i_query, va_list args );
00075
00076 static int ReSynch( demux_t *p_demux );
00077
00078 static int ReadNSVf( demux_t *p_demux );
00079 static int ReadNSVs( demux_t *p_demux );
00080
00081
00082
00083
00084 static int Open( vlc_object_t *p_this )
00085 {
00086 demux_t *p_demux = (demux_t*)p_this;
00087 demux_sys_t *p_sys;
00088
00089 uint8_t *p_peek;
00090
00091 if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
00092 return VLC_EGENERIC;
00093
00094 if( strncmp( (char *)p_peek, "NSVf", 4 )
00095 && strncmp( (char *)p_peek, "NSVs", 4 ))
00096 {
00097
00098 if( strcmp( p_demux->psz_demux, "nsv" ) || ReSynch( p_demux ) )
00099 {
00100 return VLC_EGENERIC;
00101 }
00102 }
00103
00104
00105 p_demux->pf_demux = Demux;
00106 p_demux->pf_control = Control;
00107 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00108
00109 es_format_Init( &p_sys->fmt_audio, AUDIO_ES, 0 );
00110 p_sys->p_audio = NULL;
00111
00112 es_format_Init( &p_sys->fmt_video, VIDEO_ES, 0 );
00113 p_sys->p_video = NULL;
00114
00115 es_format_Init( &p_sys->fmt_sub, SPU_ES, 0 );
00116 p_sys->p_sub = NULL;
00117
00118 p_sys->i_pcr = 1;
00119 p_sys->i_time = 0;
00120 p_sys->i_pcr_inc = 0;
00121
00122 return VLC_SUCCESS;
00123 }
00124
00125
00126
00127
00128 static void Close( vlc_object_t *p_this )
00129 {
00130 demux_t *p_demux = (demux_t*)p_this;
00131 demux_sys_t *p_sys = p_demux->p_sys;
00132
00133 free( p_sys );
00134 }
00135
00136
00137
00138
00139
00140 static int Demux( demux_t *p_demux )
00141 {
00142 demux_sys_t *p_sys = p_demux->p_sys;
00143
00144 uint8_t header[5];
00145 uint8_t *p_peek;
00146
00147 int i_size;
00148 block_t *p_frame;
00149
00150 for( ;; )
00151 {
00152 if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
00153 {
00154 msg_Warn( p_demux, "cannot peek" );
00155 return 0;
00156 }
00157
00158 if( !strncmp( (char *)p_peek, "NSVf", 4 ) )
00159 {
00160 if( ReadNSVf( p_demux ) )
00161 {
00162 return -1;
00163 }
00164 }
00165 else if( !strncmp( (char *)p_peek, "NSVs", 4 ) )
00166 {
00167 if( ReadNSVs( p_demux ) )
00168 {
00169 return -1;
00170 }
00171 break;
00172 }
00173 else if( GetWLE( p_peek ) == 0xbeef )
00174 {
00175
00176 if( stream_Read( p_demux->s, NULL, 2 ) < 2 )
00177 {
00178 msg_Warn( p_demux, "cannot read" );
00179 return 0;
00180 }
00181 break;
00182 }
00183 else
00184 {
00185 msg_Err( p_demux, "invalid signature 0x%x (%4.4s)", *(uint32_t*)p_peek, (char*)p_peek );
00186 if( ReSynch( p_demux ) )
00187 {
00188 return -1;
00189 }
00190 }
00191 }
00192
00193 if( stream_Read( p_demux->s, header, 5 ) < 5 )
00194 {
00195 msg_Warn( p_demux, "cannot read" );
00196 return 0;
00197 }
00198
00199
00200 es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
00201
00202
00203 i_size = ( header[0] >> 4 ) | ( header[1] << 4 ) | ( header[2] << 12 );
00204 if( i_size > 0 )
00205 {
00206
00207 if( (header[0]&0x0f) != 0x0 )
00208 {
00209 uint8_t aux[6];
00210 int i_aux;
00211 vlc_fourcc_t fcc;
00212 if( stream_Read( p_demux->s, aux, 6 ) < 6 )
00213 {
00214 msg_Warn( p_demux, "cannot read" );
00215 return 0;
00216 }
00217 i_aux = GetWLE( aux );
00218 fcc = VLC_FOURCC( aux[2], aux[3], aux[4], aux[5] );
00219
00220 msg_Dbg( p_demux, "Belekas: %d - size=%d fcc=%4.4s",
00221 header[0]&0xf, i_aux, (char*)&fcc );
00222
00223 if( fcc == VLC_FOURCC( 'S', 'U', 'B', 'T' ) && i_aux > 2 )
00224 {
00225 if( p_sys->p_sub == NULL )
00226 {
00227 p_sys->fmt_sub.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
00228 p_sys->p_sub = es_out_Add( p_demux->out, &p_sys->fmt_sub );
00229 es_out_Control( p_demux->out, ES_OUT_SET_ES, p_sys->p_sub );
00230 }
00231 stream_Read( p_demux->s, NULL, 2 );
00232
00233 if( ( p_frame = stream_Block( p_demux->s, i_aux - 2 ) ) )
00234 {
00235 uint8_t *p = p_frame->p_buffer;
00236
00237 while( p < &p_frame->p_buffer[p_frame->i_buffer] && *p != 0 )
00238 {
00239 p++;
00240 }
00241 if( *p == 0 && p + 1 < &p_frame->p_buffer[p_frame->i_buffer] )
00242 {
00243 p_frame->i_buffer -= p + 1 - p_frame->p_buffer;
00244 p_frame->p_buffer = p + 1;
00245 }
00246
00247
00248 p_frame->i_pts = p_sys->i_pcr;
00249 p_frame->i_dts = p_sys->i_pcr + 4000000;
00250
00251 es_out_Send( p_demux->out, p_sys->p_sub, p_frame );
00252 }
00253 }
00254 else
00255 {
00256
00257 if( stream_Read( p_demux->s, NULL, i_aux ) < i_aux )
00258 {
00259 msg_Warn( p_demux, "cannot read" );
00260 return 0;
00261 }
00262 }
00263 i_size -= 6 + i_aux;
00264 }
00265
00266
00267 if( i_size > 0 && ( p_frame = stream_Block( p_demux->s, i_size ) ) )
00268 {
00269 p_frame->i_dts = p_sys->i_pcr;
00270 es_out_Send( p_demux->out, p_sys->p_video, p_frame );
00271 }
00272 }
00273
00274
00275 i_size = header[3] | ( header[4] << 8 );
00276 if( i_size > 0 )
00277 {
00278
00279 if( p_sys->fmt_audio.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
00280 {
00281 uint8_t h[4];
00282 stream_Read( p_demux->s, h, 4 );
00283
00284 p_sys->fmt_audio.audio.i_channels = h[1];
00285 p_sys->fmt_audio.audio.i_rate = GetWLE( &h[2] );
00286
00287 i_size -= 4;
00288 }
00289 if( p_sys->p_audio == NULL )
00290 {
00291 p_sys->p_audio = es_out_Add( p_demux->out, &p_sys->fmt_audio );
00292 }
00293
00294 if( ( p_frame = stream_Block( p_demux->s, i_size ) ) )
00295 {
00296 p_frame->i_dts =
00297 p_frame->i_pts = p_sys->i_pcr;
00298 es_out_Send( p_demux->out, p_sys->p_audio, p_frame );
00299 }
00300 }
00301
00302 p_sys->i_pcr += p_sys->i_pcr_inc;
00303 if( p_sys->i_time >= 0 )
00304 {
00305 p_sys->i_time += p_sys->i_pcr_inc;
00306 }
00307
00308 return 1;
00309 }
00310
00311
00312
00313
00314 static int Control( demux_t *p_demux, int i_query, va_list args )
00315 {
00316 demux_sys_t *p_sys = p_demux->p_sys;
00317 double f, *pf;
00318 int64_t i64, *pi64;
00319
00320 switch( i_query )
00321 {
00322 case DEMUX_GET_POSITION:
00323 pf = (double*) va_arg( args, double* );
00324 i64 = stream_Size( p_demux->s );
00325 if( i64 > 0 )
00326 {
00327 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
00328 }
00329 else
00330 {
00331 *pf = 0.0;
00332 }
00333 return VLC_SUCCESS;
00334
00335 case DEMUX_SET_POSITION:
00336 f = (double) va_arg( args, double );
00337 i64 = stream_Size( p_demux->s );
00338
00339 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00340 if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) || ReSynch( p_demux ) )
00341 {
00342 return VLC_EGENERIC;
00343 }
00344 p_sys->i_time = -1;
00345 return VLC_SUCCESS;
00346
00347 case DEMUX_GET_TIME:
00348 pi64 = (int64_t*)va_arg( args, int64_t * );
00349 if( p_sys->i_time < 0 )
00350 {
00351 *pi64 = 0;
00352 return VLC_EGENERIC;
00353 }
00354 *pi64 = p_sys->i_time;
00355 return VLC_SUCCESS;
00356
00357 #if 0
00358 case DEMUX_GET_LENGTH:
00359 pi64 = (int64_t*)va_arg( args, int64_t * );
00360 if( p_sys->i_mux_rate > 0 )
00361 {
00362 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
00363 return VLC_SUCCESS;
00364 }
00365 *pi64 = 0;
00366 return VLC_EGENERIC;
00367
00368 #endif
00369 case DEMUX_GET_FPS:
00370 pf = (double*)va_arg( args, double * );
00371 *pf = (double)1000000.0 / (double)p_sys->i_pcr_inc;
00372 return VLC_SUCCESS;
00373
00374 case DEMUX_SET_TIME:
00375 default:
00376 return VLC_EGENERIC;
00377 }
00378 }
00379
00380
00381
00382
00383 static int ReSynch( demux_t *p_demux )
00384 {
00385 uint8_t *p_peek;
00386 int i_skip;
00387 int i_peek;
00388
00389 while( !p_demux->b_die )
00390 {
00391 if( ( i_peek = stream_Peek( p_demux->s, &p_peek, 1024 ) ) < 8 )
00392 {
00393 return VLC_EGENERIC;
00394 }
00395 i_skip = 0;
00396
00397 while( i_skip < i_peek - 4 )
00398 {
00399 if( !strncmp( (char *)p_peek, "NSVf", 4 )
00400 || !strncmp( (char *)p_peek, "NSVs", 4 ) )
00401 {
00402 if( i_skip > 0 )
00403 {
00404 stream_Read( p_demux->s, NULL, i_skip );
00405 }
00406 return VLC_SUCCESS;
00407 }
00408 p_peek++;
00409 i_skip++;
00410 }
00411
00412 stream_Read( p_demux->s, NULL, i_skip );
00413 }
00414 return VLC_EGENERIC;
00415 }
00416
00417
00418
00419
00420 static int ReadNSVf( demux_t *p_demux )
00421 {
00422
00423 uint8_t *p;
00424 int i_size;
00425
00426 msg_Dbg( p_demux, "new NSVf chunk" );
00427 if( stream_Peek( p_demux->s, &p, 8 ) < 8 )
00428 {
00429 return VLC_EGENERIC;
00430 }
00431
00432 i_size = GetDWLE( &p[4] );
00433 msg_Dbg( p_demux, " - size=%d", i_size );
00434
00435 return stream_Read( p_demux->s, NULL, i_size ) == i_size ? VLC_SUCCESS : VLC_EGENERIC;
00436 }
00437
00438
00439
00440 static int ReadNSVs( demux_t *p_demux )
00441 {
00442 demux_sys_t *p_sys = p_demux->p_sys;
00443 uint8_t header[19];
00444 vlc_fourcc_t fcc;
00445
00446 if( stream_Read( p_demux->s, header, 19 ) < 19 )
00447 {
00448 msg_Warn( p_demux, "cannot read" );
00449 return VLC_EGENERIC;
00450 }
00451
00452 msg_Dbg( p_demux, "new NSVs chunk" );
00453
00454 switch( ( fcc = VLC_FOURCC( header[4], header[5], header[6], header[7] ) ) )
00455 {
00456 case VLC_FOURCC( 'V', 'P', '3', ' ' ):
00457 case VLC_FOURCC( 'V', 'P', '3', '1' ):
00458 fcc = VLC_FOURCC( 'V', 'P', '3', '1' );
00459 break;
00460 case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
00461 break;
00462 default:
00463 msg_Warn( p_demux, "unknown codec" );
00464 break;
00465 }
00466 if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_video.i_codec )
00467 {
00468 es_format_Init( &p_sys->fmt_video, VIDEO_ES, fcc );
00469 p_sys->fmt_video.video.i_width = GetWLE( &header[12] );
00470 p_sys->fmt_video.video.i_height = GetWLE( &header[14] );
00471 if( p_sys->p_video )
00472 {
00473 es_out_Del( p_demux->out, p_sys->p_video );
00474 }
00475 p_sys->p_video = es_out_Add( p_demux->out, &p_sys->fmt_video );
00476
00477 msg_Dbg( p_demux, " - video `%4.4s' %dx%d",
00478 (char*)&fcc,
00479 p_sys->fmt_video.video.i_width,
00480 p_sys->fmt_video.video.i_height );
00481 }
00482
00483
00484 switch( ( fcc = VLC_FOURCC( header[8], header[9], header[10], header[11] ) ) )
00485 {
00486 case VLC_FOURCC( 'M', 'P', '3', ' ' ):
00487 fcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
00488 break;
00489 case VLC_FOURCC( 'P', 'C', 'M', ' ' ):
00490 fcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
00491 break;
00492 case VLC_FOURCC( 'A', 'A', 'C', ' ' ):
00493 case VLC_FOURCC( 'A', 'A', 'C', 'P' ):
00494 fcc = VLC_FOURCC( 'm', 'p', '4', 'a' );
00495 break;
00496 case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
00497 break;
00498 default:
00499 msg_Warn( p_demux, "unknown codec" );
00500 break;
00501 }
00502
00503 if( fcc != VLC_FOURCC( 'N', 'O', 'N', 'E' ) && fcc != p_sys->fmt_audio.i_codec )
00504 {
00505 msg_Dbg( p_demux, " - audio `%4.4s'", (char*)&fcc );
00506
00507 if( p_sys->p_audio )
00508 {
00509 es_out_Del( p_demux->out, p_sys->p_audio );
00510 p_sys->p_audio = NULL;
00511 }
00512 es_format_Init( &p_sys->fmt_audio, AUDIO_ES, fcc );
00513 }
00514
00515 if( header[16]&0x80 )
00516 {
00517
00518 switch( header[16]&0x03 )
00519 {
00520 case 0:
00521 p_sys->i_pcr_inc = 33333;
00522 break;
00523 case 1:
00524 p_sys->i_pcr_inc = 33367;
00525 break;
00526 case 2:
00527 p_sys->i_pcr_inc = 40000;
00528 break;
00529 case 3:
00530 p_sys->i_pcr_inc = 41700;
00531 break;
00532 }
00533
00534 if( header[16] < 0xc0 )
00535 p_sys->i_pcr_inc = p_sys->i_pcr_inc * (((header[16] ^ 0x80) >> 2 ) +1 );
00536 else
00537 p_sys->i_pcr_inc = p_sys->i_pcr_inc / (((header[16] ^ 0xc0) >> 2 ) +1 );
00538 }
00539 else if( header[16] != 0 )
00540 {
00541
00542 p_sys->i_pcr_inc = 1000000 / header[16];
00543 }
00544 else
00545 {
00546 msg_Dbg( p_demux, "invalid fps (0x00)" );
00547 p_sys->i_pcr_inc = 40000;
00548 }
00549 msg_Dbg( p_demux, " - fps=%.3f", 1000000.0 / (double)p_sys->i_pcr_inc );
00550
00551 return VLC_SUCCESS;
00552 }
00553