00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define PS_TK_COUNT (512 - 0xc0)
00025 #define PS_ID_TO_TK( id ) ((id) <= 0xff ? (id) - 0xc0 : \
00026 ((id)&0xff) + (256 - 0xc0))
00027
00028 typedef struct ps_psm_t ps_psm_t;
00029 static inline int ps_id_to_type( ps_psm_t *, int );
00030 static inline uint8_t *ps_id_to_lang( ps_psm_t *, int );
00031
00032 typedef struct
00033 {
00034 vlc_bool_t b_seen;
00035 int i_skip;
00036 int i_id;
00037 es_out_id_t *es;
00038 es_format_t fmt;
00039
00040 } ps_track_t;
00041
00042
00043 static inline void ps_track_init( ps_track_t tk[PS_TK_COUNT] )
00044 {
00045 int i;
00046 for( i = 0; i < PS_TK_COUNT; i++ )
00047 {
00048 tk[i].b_seen = VLC_FALSE;
00049 tk[i].i_skip = 0;
00050 tk[i].i_id = 0;
00051 tk[i].es = NULL;
00052 es_format_Init( &tk[i].fmt, UNKNOWN_ES, 0 );
00053 }
00054 }
00055
00056
00057 static inline int ps_track_fill( ps_track_t *tk, ps_psm_t *p_psm, int i_id )
00058 {
00059 tk->i_skip = 0;
00060 tk->i_id = i_id;
00061 if( ( i_id&0xff00 ) == 0xbd00 )
00062 {
00063 if( ( i_id&0xf8 ) == 0x88 )
00064 {
00065 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('d','t','s',' ') );
00066 tk->i_skip = 4;
00067 }
00068 else if( ( i_id&0xf0 ) == 0x80 )
00069 {
00070 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('a','5','2',' ') );
00071 tk->i_skip = 4;
00072 }
00073 else if( ( i_id&0xe0 ) == 0x20 )
00074 {
00075 es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('s','p','u',' ') );
00076 tk->i_skip = 1;
00077 }
00078 else if( ( i_id&0xf0 ) == 0xa0 )
00079 {
00080 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('l','p','c','m') );
00081 tk->i_skip = 1;
00082 }
00083 else if( ( i_id&0xff ) == 0x70 )
00084 {
00085 es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('o','g','t',' ') );
00086 }
00087 else if( ( i_id&0xfc ) == 0x00 )
00088 {
00089 es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('c','v','d',' ') );
00090 }
00091 else
00092 {
00093 es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
00094 return VLC_EGENERIC;
00095 }
00096 }
00097 else
00098 {
00099 int i_type = ps_id_to_type( p_psm , i_id );
00100
00101 es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
00102
00103 if( (i_id&0xf0) == 0xe0 && i_type == 0x1b )
00104 {
00105 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('h','2','6','4') );
00106 }
00107 else if( (i_id&0xf0) == 0xe0 && i_type == 0x10 )
00108 {
00109 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','4','v') );
00110 }
00111 else if( (i_id&0xf0) == 0xe0 && i_type == 0x02 )
00112 {
00113 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
00114 }
00115 else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x0f )
00116 {
00117 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('m','p','4','a') );
00118 }
00119 else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x03 )
00120 {
00121 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('m','p','g','a') );
00122 }
00123
00124 if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xf0 ) == 0xe0 )
00125 {
00126 es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
00127 }
00128 else if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xe0 ) == 0xc0 )
00129 {
00130 es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('m','p','g','a') );
00131 }
00132 else if( tk->fmt.i_cat == UNKNOWN_ES ) return VLC_EGENERIC;
00133 }
00134
00135
00136 tk->fmt.b_packetized = VLC_FALSE;
00137
00138 if( ps_id_to_lang( p_psm , i_id ) )
00139 {
00140 tk->fmt.psz_language = malloc( 4 );
00141 memcpy( tk->fmt.psz_language, ps_id_to_lang( p_psm , i_id ), 3 );
00142 tk->fmt.psz_language[3] = 0;
00143 }
00144
00145 return VLC_SUCCESS;
00146 }
00147
00148
00149 static inline int ps_pkt_id( block_t *p_pkt )
00150 {
00151 if( p_pkt->p_buffer[3] == 0xbd &&
00152 p_pkt->i_buffer >= 9 &&
00153 p_pkt->i_buffer >= 9 + p_pkt->p_buffer[8] )
00154 {
00155 return 0xbd00 | p_pkt->p_buffer[9+p_pkt->p_buffer[8]];
00156 }
00157 return p_pkt->p_buffer[3];
00158 }
00159
00160
00161
00162
00163 static inline int ps_pkt_size( uint8_t *p, int i_peek )
00164 {
00165 if( p[3] == 0xb9 && i_peek >= 4 )
00166 {
00167 return 4;
00168 }
00169 else if( p[3] == 0xba )
00170 {
00171 if( (p[4] >> 6) == 0x01 && i_peek >= 14 )
00172 {
00173 return 14 + (p[13]&0x07);
00174 }
00175 else if( (p[4] >> 4) == 0x02 && i_peek >= 12 )
00176 {
00177 return 12;
00178 }
00179 return -1;
00180 }
00181 else if( i_peek >= 6 )
00182 {
00183 return 6 + ((p[4]<<8) | p[5] );
00184 }
00185 return -1;
00186 }
00187
00188
00189 static inline int ps_pkt_parse_pack( block_t *p_pkt, int64_t *pi_scr,
00190 int *pi_mux_rate )
00191 {
00192 uint8_t *p = p_pkt->p_buffer;
00193 if( p_pkt->i_buffer >= 14 && (p[4] >> 6) == 0x01 )
00194 {
00195 *pi_scr =((((int64_t)p[4]&0x38) << 27 )|
00196 (((int64_t)p[4]&0x03) << 28 )|
00197 ((int64_t)p[5] << 20 )|
00198 (((int64_t)p[6]&0xf8) << 12 )|
00199 (((int64_t)p[6]&0x03) << 13 )|
00200 ((int64_t)p[7] << 5 )|
00201 ((int64_t)p[8] >> 3 )) * 100 / 9;
00202
00203 *pi_mux_rate = ( p[10] << 14 )|( p[11] << 6 )|( p[12] >> 2);
00204 }
00205 else if( p_pkt->i_buffer >= 12 && (p[4] >> 4) == 0x02 )
00206 {
00207 *pi_scr =((((int64_t)p[4]&0x0e) << 29 )|
00208 ((int64_t)p[5] << 22 )|
00209 (((int64_t)p[6]&0xfe) << 14 )|
00210 ((int64_t)p[7] << 7 )|
00211 ((int64_t)p[8] >> 1 )) * 100 / 9;
00212
00213 *pi_mux_rate = ( ( p[9]&0x7f )<< 15 )|( p[10] << 7 )|( p[11] >> 1);
00214 }
00215 else
00216 {
00217 return VLC_EGENERIC;
00218 }
00219 return VLC_SUCCESS;
00220 }
00221
00222
00223 static inline int ps_pkt_parse_system( block_t *p_pkt, ps_psm_t *p_psm,
00224 ps_track_t tk[PS_TK_COUNT] )
00225 {
00226 uint8_t *p = &p_pkt->p_buffer[6 + 3 + 1 + 1 + 1];
00227
00228
00229
00230 while( p < &p_pkt->p_buffer[p_pkt->i_buffer] )
00231 {
00232 int i_id = p[0];
00233
00234
00235 if( p[0] >= 0xBC || p[0] == 0xB8 || p[0] == 0xB9 ) p += 2;
00236 p++;
00237
00238 if( i_id >= 0xc0 )
00239 {
00240 int i_tk = PS_ID_TO_TK( i_id );
00241
00242 if( !tk[i_tk].b_seen )
00243 {
00244 if( !ps_track_fill( &tk[i_tk], p_psm, i_id ) )
00245 {
00246 tk[i_tk].b_seen = VLC_TRUE;
00247 }
00248 }
00249 }
00250 }
00251 return VLC_SUCCESS;
00252 }
00253
00254
00255 static inline int ps_pkt_parse_pes( block_t *p_pes, int i_skip_extra )
00256 {
00257 uint8_t header[30];
00258 int i_skip = 0;
00259
00260 memcpy( header, p_pes->p_buffer, __MIN( p_pes->i_buffer, 30 ) );
00261
00262 switch( header[3] )
00263 {
00264 case 0xBC:
00265 case 0xBE:
00266 case 0xBF:
00267 case 0xB0:
00268 case 0xB1:
00269 case 0xFF:
00270 case 0xF2:
00271 case 0xF8:
00272 i_skip = 6;
00273 break;
00274
00275 default:
00276 if( ( header[6]&0xC0 ) == 0x80 )
00277 {
00278
00279 i_skip = header[8] + 9;
00280
00281 if( header[7]&0x80 )
00282 {
00283 p_pes->i_pts = ((mtime_t)(header[ 9]&0x0e ) << 29)|
00284 (mtime_t)(header[10] << 22)|
00285 ((mtime_t)(header[11]&0xfe) << 14)|
00286 (mtime_t)(header[12] << 7)|
00287 (mtime_t)(header[13] >> 1);
00288
00289 if( header[7]&0x40 )
00290 {
00291 p_pes->i_dts = ((mtime_t)(header[14]&0x0e ) << 29)|
00292 (mtime_t)(header[15] << 22)|
00293 ((mtime_t)(header[16]&0xfe) << 14)|
00294 (mtime_t)(header[17] << 7)|
00295 (mtime_t)(header[18] >> 1);
00296 }
00297 }
00298 }
00299 else
00300 {
00301 i_skip = 6;
00302 while( i_skip < 23 && header[i_skip] == 0xff )
00303 {
00304 i_skip++;
00305 }
00306 if( i_skip == 23 )
00307 {
00308
00309 return VLC_EGENERIC;
00310 }
00311 if( ( header[i_skip] & 0xC0 ) == 0x40 )
00312 {
00313 i_skip += 2;
00314 }
00315
00316 if( header[i_skip]&0x20 )
00317 {
00318 p_pes->i_pts = ((mtime_t)(header[i_skip]&0x0e ) << 29)|
00319 (mtime_t)(header[i_skip+1] << 22)|
00320 ((mtime_t)(header[i_skip+2]&0xfe) << 14)|
00321 (mtime_t)(header[i_skip+3] << 7)|
00322 (mtime_t)(header[i_skip+4] >> 1);
00323
00324 if( header[i_skip]&0x10 )
00325 {
00326 p_pes->i_dts = ((mtime_t)(header[i_skip+5]&0x0e ) << 29)|
00327 (mtime_t)(header[i_skip+6] << 22)|
00328 ((mtime_t)(header[i_skip+7]&0xfe) << 14)|
00329 (mtime_t)(header[i_skip+8] << 7)|
00330 (mtime_t)(header[i_skip+9] >> 1);
00331 i_skip += 10;
00332 }
00333 else
00334 {
00335 i_skip += 5;
00336 }
00337 }
00338 else
00339 {
00340 i_skip += 1;
00341 }
00342 }
00343 }
00344
00345 i_skip += i_skip_extra;
00346
00347 if( p_pes->i_buffer <= i_skip )
00348 {
00349 return VLC_EGENERIC;
00350 }
00351
00352 p_pes->p_buffer += i_skip;
00353 p_pes->i_buffer -= i_skip;
00354
00355 p_pes->i_dts = 100 * p_pes->i_dts / 9;
00356 p_pes->i_pts = 100 * p_pes->i_pts / 9;
00357
00358 return VLC_SUCCESS;
00359 }
00360
00361
00362 typedef struct ps_es_t
00363 {
00364 int i_type;
00365 int i_id;
00366
00367 int i_descriptor;
00368 uint8_t *p_descriptor;
00369
00370
00371 uint8_t lang[3];
00372
00373 } ps_es_t;
00374
00375 struct ps_psm_t
00376 {
00377 int i_version;
00378
00379 int i_es;
00380 ps_es_t **es;
00381 };
00382
00383 static inline int ps_id_to_type( ps_psm_t *p_psm, int i_id )
00384 {
00385 int i;
00386 for( i = 0; p_psm && i < p_psm->i_es; i++ )
00387 {
00388 if( p_psm->es[i]->i_id == i_id ) return p_psm->es[i]->i_type;
00389 }
00390 return 0;
00391 }
00392
00393 static inline uint8_t *ps_id_to_lang( ps_psm_t *p_psm, int i_id )
00394 {
00395 int i;
00396 for( i = 0; p_psm && i < p_psm->i_es; i++ )
00397 {
00398 if( p_psm->es[i]->i_id == i_id ) return p_psm->es[i]->lang;
00399 }
00400 return 0;
00401 }
00402
00403 static inline void ps_psm_init( ps_psm_t *p_psm )
00404 {
00405 p_psm->i_version = 0xFFFF;
00406 p_psm->i_es = 0;
00407 p_psm->es = 0;
00408 }
00409
00410 static inline void ps_psm_destroy( ps_psm_t *p_psm )
00411 {
00412 while( p_psm->i_es-- )
00413 {
00414 if( p_psm->es[p_psm->i_es]->i_descriptor )
00415 free( p_psm->es[p_psm->i_es]->p_descriptor );
00416 free( p_psm->es[p_psm->i_es] );
00417 }
00418 if( p_psm->es ) free( p_psm->es );
00419
00420 p_psm->es = 0;
00421 p_psm->i_es = 0;
00422 }
00423
00424 static inline int ps_psm_fill( ps_psm_t *p_psm, block_t *p_pkt,
00425 ps_track_t tk[PS_TK_COUNT], es_out_t *out )
00426 {
00427 int i_buffer = p_pkt->i_buffer;
00428 uint8_t *p_buffer = p_pkt->p_buffer;
00429 int i_length, i_version, i_info_length, i_esm_length, i_es_base, i;
00430
00431 if( !p_psm || p_buffer[3] != 0xbc ) return VLC_EGENERIC;
00432
00433 i_length = (uint16_t)(p_buffer[4] << 8) + p_buffer[5] + 6;
00434 if( i_length > i_buffer ) return VLC_EGENERIC;
00435
00436
00437 i_version = (p_buffer[6] && 0xf8);
00438
00439 if( p_psm->i_version == i_version ) return VLC_EGENERIC;
00440
00441 ps_psm_destroy( p_psm );
00442
00443 i_info_length = (uint16_t)(p_buffer[8] << 8) + p_buffer[9];
00444 if( i_info_length + 10 > i_length ) return VLC_EGENERIC;
00445
00446
00447 i_esm_length = (uint16_t)(p_buffer[ 10 + i_info_length ] << 8) +
00448 p_buffer[ 11 + i_info_length];
00449 i_es_base = 12 + i_info_length;
00450
00451 while( i_es_base + 4 < i_length )
00452 {
00453 ps_es_t es;
00454 es.lang[0] = es.lang[1] = es.lang[2] = 0;
00455
00456 es.i_type = p_buffer[ i_es_base ];
00457 es.i_id = p_buffer[ i_es_base + 1 ];
00458 i_info_length = (uint16_t)(p_buffer[ i_es_base + 2 ] << 8) +
00459 p_buffer[ i_es_base + 3 ];
00460
00461 if( i_es_base + 4 + i_info_length > i_length ) break;
00462
00463 es.p_descriptor = 0;
00464 es.i_descriptor = i_info_length;
00465 if( i_info_length > 0 )
00466 {
00467 int i = 0;
00468
00469 es.p_descriptor = malloc( i_info_length );
00470 memcpy( es.p_descriptor, p_buffer + i_es_base + 4, i_info_length);
00471
00472 while( i <= es.i_descriptor - 2 )
00473 {
00474
00475 if( es.p_descriptor[i] != 0x0a )
00476 {
00477 i += es.p_descriptor[i+1] + 2;
00478 continue;
00479 }
00480
00481 if( i <= es.i_descriptor - 6 )
00482 {
00483 es.lang[0] = es.p_descriptor[i+2];
00484 es.lang[1] = es.p_descriptor[i+3];
00485 es.lang[2] = es.p_descriptor[i+4];
00486 }
00487 break;
00488 }
00489 }
00490
00491 p_psm->es = realloc( p_psm->es, sizeof(ps_es_t *) * (p_psm->i_es+1) );
00492 p_psm->es[p_psm->i_es] = malloc( sizeof(ps_es_t) );
00493 *p_psm->es[p_psm->i_es++] = es;
00494 i_es_base += 4 + i_info_length;
00495 }
00496
00497
00498
00499 p_psm->i_version = i_version;
00500
00501
00502 for( i = 0; i < PS_TK_COUNT; i++ )
00503 {
00504 ps_track_t tk_tmp;
00505
00506 if( !tk[i].b_seen || !tk[i].es ) continue;
00507
00508 if( ps_track_fill( &tk_tmp, p_psm, tk[i].i_id ) != VLC_SUCCESS )
00509 continue;
00510
00511 if( tk_tmp.fmt.i_codec == tk[i].fmt.i_codec ) continue;
00512
00513 es_out_Del( out, tk[i].es );
00514 tk[i] = tk_tmp;
00515 tk[i].b_seen = VLC_TRUE;
00516 tk[i].es = es_out_Add( out, &tk[i].fmt );
00517 }
00518
00519 return VLC_SUCCESS;
00520 }