| 83 | | decoder_t *p_dec = (decoder_t*)p_this; |
|---|
| 84 | | |
|---|
| 85 | | p_dec->pf_run = Run; |
|---|
| 86 | | |
|---|
| 87 | | return VLC_SUCCESS; |
|---|
| 88 | | } |
|---|
| 89 | | |
|---|
| 90 | | /***************************************************************************** |
|---|
| 91 | | * Run: this function is called just after the thread is created |
|---|
| 92 | | *****************************************************************************/ |
|---|
| 93 | | static int Run( decoder_fifo_t *p_fifo ) |
|---|
| 94 | | { |
|---|
| 95 | | packetizer_thread_t *p_pack; |
|---|
| 96 | | int i_ret; |
|---|
| 97 | | |
|---|
| 98 | | msg_Dbg( p_fifo, "Running copy packetizer (fcc=%4.4s)", |
|---|
| 99 | | (char*)&p_fifo->i_fourcc ); |
|---|
| 100 | | |
|---|
| 101 | | p_pack = malloc( sizeof( packetizer_thread_t ) ); |
|---|
| 102 | | memset( p_pack, 0, sizeof( packetizer_thread_t ) ); |
|---|
| 103 | | |
|---|
| 104 | | p_pack->p_fifo = p_fifo; |
|---|
| 105 | | |
|---|
| 106 | | if( Init( p_pack ) ) |
|---|
| 107 | | { |
|---|
| 108 | | DecoderError( p_fifo ); |
|---|
| | 68 | decoder_t *p_dec = (decoder_t*)p_this; |
|---|
| | 69 | decoder_sys_t *p_sys; |
|---|
| | 70 | |
|---|
| | 71 | if( p_dec->fmt_in.i_cat == AUDIO_ES || p_dec->fmt_in.i_cat == VIDEO_ES ) |
|---|
| | 72 | { |
|---|
| | 73 | p_dec->pf_packetize = PacketizeAV; |
|---|
| | 74 | } |
|---|
| | 75 | else if( p_dec->fmt_in.i_cat == SPU_ES ) |
|---|
| | 76 | { |
|---|
| | 77 | if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', ' ' ) || |
|---|
| | 78 | p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ) |
|---|
| | 79 | { |
|---|
| | 80 | p_dec->pf_packetize = PacketizeSPU; |
|---|
| | 81 | } |
|---|
| | 82 | else |
|---|
| | 83 | { |
|---|
| | 84 | p_dec->pf_packetize = PacketizeAV; |
|---|
| | 85 | } |
|---|
| | 86 | } |
|---|
| | 87 | else |
|---|
| | 88 | { |
|---|
| | 89 | msg_Err( p_dec, "invalid ES type" ); |
|---|
| 112 | | while( !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error ) |
|---|
| 113 | | { |
|---|
| 114 | | p_pack->pf_packetize( p_pack ); |
|---|
| 115 | | } |
|---|
| 116 | | |
|---|
| 117 | | if( p_pack->p_fifo->b_error ) |
|---|
| 118 | | { |
|---|
| 119 | | DecoderError( p_pack->p_fifo ); |
|---|
| 120 | | } |
|---|
| 121 | | |
|---|
| 122 | | i_ret = p_pack->p_fifo->b_error ? VLC_EGENERIC : VLC_SUCCESS; |
|---|
| 123 | | End( p_pack ); |
|---|
| 124 | | |
|---|
| 125 | | return( i_ret ); |
|---|
| 126 | | } |
|---|
| 127 | | |
|---|
| 128 | | /***************************************************************************** |
|---|
| 129 | | * Init: initialize data before entering main loop |
|---|
| 130 | | *****************************************************************************/ |
|---|
| 131 | | static int Init( packetizer_thread_t *p_pack ) |
|---|
| 132 | | { |
|---|
| 133 | | |
|---|
| 134 | | p_pack->pf_packetize = PacketizeStd; |
|---|
| 135 | | |
|---|
| 136 | | switch( p_pack->p_fifo->i_fourcc ) |
|---|
| | 93 | /* Create the output format */ |
|---|
| | 94 | memcpy( &p_dec->fmt_out, &p_dec->fmt_in, sizeof( es_format_t ) ); |
|---|
| | 95 | if( p_dec->fmt_in.i_extra > 0 ) |
|---|
| | 96 | { |
|---|
| | 97 | p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra ); |
|---|
| | 98 | memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, |
|---|
| | 99 | p_dec->fmt_in.i_extra ); |
|---|
| | 100 | } |
|---|
| | 101 | |
|---|
| | 102 | /* Fix the value of the fourcc */ |
|---|
| | 103 | switch( p_dec->fmt_in.i_codec ) |
|---|
| | 181 | switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) |
|---|
| | 182 | { |
|---|
| | 183 | case 1: |
|---|
| | 184 | p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' '); |
|---|
| | 185 | break; |
|---|
| | 186 | case 2: |
|---|
| | 187 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); |
|---|
| | 188 | break; |
|---|
| | 189 | case 3: |
|---|
| | 190 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); |
|---|
| | 191 | break; |
|---|
| | 192 | case 4: |
|---|
| | 193 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); |
|---|
| | 194 | break; |
|---|
| | 195 | default: |
|---|
| | 196 | msg_Err( p_dec, "unknown raw audio sample size !!" ); |
|---|
| | 197 | return VLC_EGENERIC; |
|---|
| | 198 | } |
|---|
| | 199 | break; |
|---|
| | 200 | |
|---|
| | 201 | case VLC_FOURCC( 't', 'w', 'o', 's' ): |
|---|
| | 202 | switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) |
|---|
| | 203 | { |
|---|
| | 204 | case 1: |
|---|
| | 205 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); |
|---|
| | 206 | break; |
|---|
| | 207 | case 2: |
|---|
| | 208 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b'); |
|---|
| | 209 | break; |
|---|
| | 210 | case 3: |
|---|
| | 211 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b'); |
|---|
| | 212 | break; |
|---|
| | 213 | case 4: |
|---|
| | 214 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b'); |
|---|
| | 215 | break; |
|---|
| | 216 | default: |
|---|
| | 217 | msg_Err( p_dec, "unknown raw audio sample size !!" ); |
|---|
| | 218 | return VLC_EGENERIC; |
|---|
| | 219 | } |
|---|
| | 220 | break; |
|---|
| | 221 | |
|---|
| | 222 | case VLC_FOURCC( 's', 'o', 'w', 't' ): |
|---|
| | 223 | switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) |
|---|
| | 224 | { |
|---|
| | 225 | case 1: |
|---|
| | 226 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); |
|---|
| | 227 | break; |
|---|
| | 228 | case 2: |
|---|
| | 229 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); |
|---|
| | 230 | break; |
|---|
| | 231 | case 3: |
|---|
| | 232 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); |
|---|
| | 233 | break; |
|---|
| | 234 | case 4: |
|---|
| | 235 | p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); |
|---|
| | 236 | break; |
|---|
| | 237 | default: |
|---|
| | 238 | msg_Err( p_dec, "unknown raw audio sample size !!" ); |
|---|
| | 239 | return VLC_EGENERIC; |
|---|
| | 240 | } |
|---|
| | 241 | break; |
|---|
| | 242 | |
|---|
| | 243 | /* subtitles */ |
|---|
| | 244 | case VLC_FOURCC( 's', 'p', 'u', 'b' ): |
|---|
| | 245 | p_dec->fmt_out.i_codec = VLC_FOURCC( 's', 'p', 'u', ' ' ); |
|---|
| | 246 | break; |
|---|
| | 247 | } |
|---|
| | 248 | |
|---|
| | 249 | p_dec->p_sys = p_sys = malloc( sizeof( block_t ) ); |
|---|
| | 250 | p_sys->i_spu_size = 0; |
|---|
| | 251 | p_sys->i_spu = 0; |
|---|
| | 252 | p_sys->p_block = NULL; |
|---|
| | 253 | |
|---|
| | 254 | return VLC_SUCCESS; |
|---|
| | 255 | } |
|---|
| | 256 | |
|---|
| | 257 | /***************************************************************************** |
|---|
| | 258 | * Close: |
|---|
| | 259 | *****************************************************************************/ |
|---|
| | 260 | static void Close( vlc_object_t *p_this ) |
|---|
| | 261 | { |
|---|
| | 262 | decoder_t *p_dec = (decoder_t*)p_this; |
|---|
| | 263 | |
|---|
| | 264 | if( p_dec->p_sys->p_block ) |
|---|
| | 265 | { |
|---|
| | 266 | block_ChainRelease( p_dec->p_sys->p_block ); |
|---|
| | 267 | } |
|---|
| | 268 | |
|---|
| | 269 | free( p_dec->p_sys ); |
|---|
| | 270 | } |
|---|
| | 271 | |
|---|
| | 272 | /***************************************************************************** |
|---|
| | 273 | * PacketizeStd: packetize an unit (here copy a complete block ) |
|---|
| | 274 | *****************************************************************************/ |
|---|
| | 275 | static block_t *PacketizeAV ( decoder_t *p_dec, block_t **pp_block ) |
|---|
| | 276 | { |
|---|
| | 277 | block_t *p_block; |
|---|
| | 278 | block_t *p_ret = p_dec->p_sys->p_block; |
|---|
| | 279 | |
|---|
| | 280 | if( pp_block == NULL || *pp_block == NULL ) |
|---|
| | 281 | { |
|---|
| | 282 | return NULL; |
|---|
| | 283 | } |
|---|
| | 284 | p_block = *pp_block; |
|---|
| | 285 | *pp_block = NULL; |
|---|
| | 286 | |
|---|
| | 287 | if( p_block->i_pts <= 0 ) |
|---|
| | 288 | { |
|---|
| | 289 | msg_Dbg( p_dec, "need pts > 0" ); |
|---|
| | 290 | block_Release( p_block ); |
|---|
| | 291 | return NULL; |
|---|
| | 292 | } |
|---|
| | 293 | |
|---|
| | 294 | if( p_ret != NULL && p_block->i_pts > p_ret->i_pts ) |
|---|
| | 295 | { |
|---|
| | 296 | p_ret->i_length = p_block->i_pts - p_ret->i_pts; |
|---|
| | 297 | } |
|---|
| | 298 | p_dec->p_sys->p_block = p_block; |
|---|
| | 299 | |
|---|
| | 300 | return p_ret; |
|---|
| | 301 | } |
|---|
| | 302 | |
|---|
| | 303 | /***************************************************************************** |
|---|
| | 304 | * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle) |
|---|
| | 305 | *****************************************************************************/ |
|---|
| | 306 | static block_t *PacketizeSPU( decoder_t *p_dec, block_t **pp_block ) |
|---|
| | 307 | { |
|---|
| | 308 | decoder_sys_t *p_sys = p_dec->p_sys; |
|---|
| | 309 | block_t *p_block; |
|---|
| | 310 | |
|---|
| | 311 | if( pp_block == NULL || *pp_block == NULL ) |
|---|
| | 312 | { |
|---|
| | 313 | return NULL; |
|---|
| | 314 | } |
|---|
| | 315 | p_block = *pp_block; |
|---|
| | 316 | *pp_block = NULL; |
|---|
| | 317 | |
|---|
| | 318 | if( p_sys->i_spu_size <= 0 && |
|---|
| | 319 | ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) ) |
|---|
| | 320 | { |
|---|
| | 321 | msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" ); |
|---|
| | 322 | block_Release( p_block ); |
|---|
| | 323 | return NULL; |
|---|
| | 324 | } |
|---|
| | 325 | |
|---|
| | 326 | block_ChainAppend( &p_sys->p_block, p_block ); |
|---|
| | 327 | p_sys->i_spu += p_block->i_buffer; |
|---|
| | 328 | |
|---|
| | 329 | if( p_sys->i_spu_size <= 0 ) |
|---|
| | 330 | { |
|---|
| | 331 | int i_rle = ( ( p_block->p_buffer[2] << 8 )| p_block->p_buffer[3] ) - 4; |
|---|
| | 332 | |
|---|
| | 333 | p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )| p_block->p_buffer[1]; |
|---|
| | 334 | |
|---|
| | 335 | msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d", p_sys->i_spu_size, i_rle ); |
|---|
| | 336 | |
|---|
| | 337 | if( p_sys->i_spu_size <= 0 || i_rle >= p_sys->i_spu_size ) |
|---|
| 288 | | case VLC_FOURCC( 't', 'w', 'o', 's' ): |
|---|
| 289 | | { |
|---|
| 290 | | WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; |
|---|
| 291 | | if( p_wf ) |
|---|
| 292 | | { |
|---|
| 293 | | switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) |
|---|
| 294 | | { |
|---|
| 295 | | case 1: |
|---|
| 296 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' '); |
|---|
| 297 | | break; |
|---|
| 298 | | case 2: |
|---|
| 299 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b'); |
|---|
| 300 | | break; |
|---|
| 301 | | case 3: |
|---|
| 302 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b'); |
|---|
| 303 | | break; |
|---|
| 304 | | case 4: |
|---|
| 305 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b'); |
|---|
| 306 | | break; |
|---|
| 307 | | default: |
|---|
| 308 | | msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); |
|---|
| 309 | | return VLC_EGENERIC; |
|---|
| 310 | | } |
|---|
| 311 | | } |
|---|
| 312 | | else |
|---|
| 313 | | { |
|---|
| 314 | | msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); |
|---|
| 315 | | return VLC_EGENERIC; |
|---|
| 316 | | } |
|---|
| 317 | | p_pack->output_format.i_cat = AUDIO_ES; |
|---|
| 318 | | break; |
|---|
| 319 | | } |
|---|
| 320 | | case VLC_FOURCC( 's', 'o', 'w', 't' ): |
|---|
| 321 | | { |
|---|
| 322 | | WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; |
|---|
| 323 | | if( p_wf ) |
|---|
| 324 | | { |
|---|
| 325 | | switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) |
|---|
| 326 | | { |
|---|
| 327 | | case 1: |
|---|
| 328 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' '); |
|---|
| 329 | | break; |
|---|
| 330 | | case 2: |
|---|
| 331 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l'); |
|---|
| 332 | | break; |
|---|
| 333 | | case 3: |
|---|
| 334 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l'); |
|---|
| 335 | | break; |
|---|
| 336 | | case 4: |
|---|
| 337 | | p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l'); |
|---|
| 338 | | break; |
|---|
| 339 | | default: |
|---|
| 340 | | msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); |
|---|
| 341 | | return VLC_EGENERIC; |
|---|
| 342 | | } |
|---|
| 343 | | } |
|---|
| 344 | | else |
|---|
| 345 | | { |
|---|
| 346 | | msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); |
|---|
| 347 | | return VLC_EGENERIC; |
|---|
| 348 | | } |
|---|
| 349 | | p_pack->output_format.i_cat = AUDIO_ES; |
|---|
| 350 | | break; |
|---|
| 351 | | } |
|---|
| 352 | | |
|---|
| 353 | | /* subtitles */ |
|---|
| 354 | | case VLC_FOURCC( 's', 'p', 'u', ' ' ): /* DVD */ |
|---|
| 355 | | case VLC_FOURCC( 's', 'p', 'u', 'b' ): |
|---|
| 356 | | p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'p', 'u', ' ' ); |
|---|
| 357 | | p_pack->output_format.i_cat = SPU_ES; |
|---|
| 358 | | p_pack->pf_packetize = PacketizeSPU; |
|---|
| 359 | | break; |
|---|
| 360 | | |
|---|
| 361 | | case VLC_FOURCC( 's', 'u', 'b', 't' ): |
|---|
| 362 | | p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'u', 'b', 't' ); |
|---|
| 363 | | p_pack->output_format.i_cat = SPU_ES; |
|---|
| 364 | | break; |
|---|
| 365 | | |
|---|
| 366 | | default: |
|---|
| 367 | | msg_Err( p_pack->p_fifo, "unknown es type !!" ); |
|---|
| 368 | | return VLC_EGENERIC; |
|---|
| 369 | | } |
|---|
| 370 | | |
|---|
| 371 | | switch( p_pack->output_format.i_cat ) |
|---|
| 372 | | { |
|---|
| 373 | | case AUDIO_ES: |
|---|
| 374 | | { |
|---|
| 375 | | WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; |
|---|
| 376 | | if( p_wf ) |
|---|
| 377 | | { |
|---|
| 378 | | p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec; |
|---|
| 379 | | p_pack->output_format.i_channels = p_wf->nChannels; |
|---|
| 380 | | p_pack->output_format.i_block_align = p_wf->nBlockAlign; |
|---|
| 381 | | p_pack->output_format.i_bitrate = p_wf->nAvgBytesPerSec * 8; |
|---|
| 382 | | p_pack->output_format.i_extra_data = p_wf->cbSize; |
|---|
| 383 | | if( p_wf->cbSize > 0 ) |
|---|
| 384 | | { |
|---|
| 385 | | p_pack->output_format.p_extra_data = |
|---|
| 386 | | malloc( p_pack->output_format.i_extra_data ); |
|---|
| 387 | | memcpy( p_pack->output_format.p_extra_data, |
|---|
| 388 | | &p_wf[1], |
|---|
| 389 | | p_pack->output_format.i_extra_data ); |
|---|
| 390 | | } |
|---|
| 391 | | else |
|---|
| 392 | | { |
|---|
| 393 | | p_pack->output_format.p_extra_data = NULL; |
|---|
| 394 | | } |
|---|
| 395 | | } |
|---|
| 396 | | else |
|---|
| 397 | | { |
|---|
| 398 | | p_pack->output_format.i_sample_rate = 0; |
|---|
| 399 | | p_pack->output_format.i_channels = 0; |
|---|
| 400 | | p_pack->output_format.i_block_align = 0; |
|---|
| 401 | | p_pack->output_format.i_bitrate = 0; |
|---|
| 402 | | p_pack->output_format.i_extra_data = 0; |
|---|
| 403 | | p_pack->output_format.p_extra_data = NULL; |
|---|
| 404 | | } |
|---|
| 405 | | } |
|---|
| 406 | | break; |
|---|
| 407 | | |
|---|
| 408 | | case VIDEO_ES: |
|---|
| 409 | | { |
|---|
| 410 | | BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader; |
|---|
| 411 | | |
|---|
| 412 | | p_pack->output_format.i_bitrate = 0; |
|---|
| 413 | | if( p_bih ) |
|---|
| 414 | | { |
|---|
| 415 | | p_pack->output_format.i_width = p_bih->biWidth; |
|---|
| 416 | | p_pack->output_format.i_height = p_bih->biHeight; |
|---|
| 417 | | p_pack->output_format.i_extra_data = p_bih->biSize - sizeof( BITMAPINFOHEADER ); |
|---|
| 418 | | if( p_pack->output_format.i_extra_data > 0 ) |
|---|
| 419 | | { |
|---|
| 420 | | p_pack->output_format.p_extra_data = |
|---|
| 421 | | malloc( p_pack->output_format.i_extra_data ); |
|---|
| 422 | | memcpy( p_pack->output_format.p_extra_data, |
|---|
| 423 | | &p_bih[1], |
|---|
| 424 | | p_pack->output_format.i_extra_data ); |
|---|
| 425 | | } |
|---|
| 426 | | } |
|---|
| 427 | | else |
|---|
| 428 | | { |
|---|
| 429 | | p_pack->output_format.i_width = 0; |
|---|
| 430 | | p_pack->output_format.i_height = 0; |
|---|
| 431 | | p_pack->output_format.i_extra_data = 0; |
|---|
| 432 | | p_pack->output_format.p_extra_data = NULL; |
|---|
| 433 | | } |
|---|
| 434 | | } |
|---|
| 435 | | break; |
|---|
| 436 | | |
|---|
| 437 | | case SPU_ES: |
|---|
| 438 | | p_pack->output_format.i_extra_data = 0; |
|---|
| 439 | | p_pack->output_format.p_extra_data = NULL; |
|---|
| 440 | | break; |
|---|
| 441 | | |
|---|
| 442 | | default: |
|---|
| 443 | | return VLC_EGENERIC; |
|---|
| 444 | | } |
|---|
| 445 | | |
|---|
| 446 | | p_pack->p_sout_input = |
|---|
| 447 | | sout_InputNew( p_pack->p_fifo, |
|---|
| 448 | | &p_pack->output_format ); |
|---|
| 449 | | |
|---|
| 450 | | if( !p_pack->p_sout_input ) |
|---|
| 451 | | { |
|---|
| 452 | | msg_Err( p_pack->p_fifo, "cannot add a new stream" ); |
|---|
| 453 | | return VLC_EGENERIC; |
|---|
| 454 | | } |
|---|
| 455 | | |
|---|
| 456 | | return( VLC_SUCCESS ); |
|---|
| | 346 | } |
|---|
| | 347 | |
|---|
| | 348 | if( p_sys->i_spu >= p_sys->i_spu_size ) |
|---|
| | 349 | { |
|---|
| | 350 | /* We have a complete sub */ |
|---|
| | 351 | block_t *p_ret = p_sys->p_block; |
|---|
| | 352 | |
|---|
| | 353 | msg_Dbg( p_dec, "SPU packets size=%d should be %d", |
|---|
| | 354 | p_sys->i_spu, p_sys->i_spu_size ); |
|---|
| | 355 | |
|---|
| | 356 | p_sys->i_spu_size = 0; |
|---|
| | 357 | p_sys->i_spu = 0; |
|---|
| | 358 | p_sys->p_block = NULL; |
|---|
| | 359 | return p_ret; |
|---|
| | 360 | } |
|---|
| | 361 | return NULL; |
|---|
| 459 | | /***************************************************************************** |
|---|
| 460 | | * PacketizeStd: packetize an unit (here copy a complete pes) |
|---|
| 461 | | *****************************************************************************/ |
|---|
| 462 | | static void PacketizeStd( packetizer_thread_t *p_pack ) |
|---|
| 463 | | { |
|---|
| 464 | | sout_buffer_t *p_out = NULL; |
|---|
| 465 | | pes_packet_t *p_pes; |
|---|
| 466 | | |
|---|
| 467 | | input_ExtractPES( p_pack->p_fifo, &p_pes ); |
|---|
| 468 | | if( !p_pes ) |
|---|
| 469 | | { |
|---|
| 470 | | p_pack->p_fifo->b_error = 1; |
|---|
| 471 | | return; |
|---|
| 472 | | } |
|---|
| 473 | | #if 0 |
|---|
| 474 | | msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd, |
|---|
| 475 | | p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts ); |
|---|
| 476 | | #endif |
|---|
| 477 | | |
|---|
| 478 | | if( p_pes->i_pts <= 0 ) |
|---|
| 479 | | { |
|---|
| 480 | | msg_Dbg( p_pack->p_fifo, "need pts != 0" ); |
|---|
| 481 | | input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); |
|---|
| 482 | | return; |
|---|
| 483 | | } |
|---|
| 484 | | |
|---|
| 485 | | if( p_pes->i_pes_size > 0 ) |
|---|
| 486 | | { |
|---|
| 487 | | pes_packet_t *p_next; |
|---|
| 488 | | |
|---|
| 489 | | AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes ); |
|---|
| 490 | | |
|---|
| 491 | | input_ShowPES( p_pack->p_fifo, &p_next ); |
|---|
| 492 | | if( p_next && p_next->i_pts > 0 ) |
|---|
| 493 | | { |
|---|
| 494 | | p_out->i_length = p_next->i_pts - p_pes->i_pts; |
|---|
| 495 | | } |
|---|
| 496 | | |
|---|
| 497 | | sout_InputSendBuffer( p_pack->p_sout_input, |
|---|
| 498 | | p_out ); |
|---|
| 499 | | } |
|---|
| 500 | | |
|---|
| 501 | | input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); |
|---|
| 502 | | } |
|---|
| 503 | | |
|---|
| 504 | | /***************************************************************************** |
|---|
| 505 | | * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle) |
|---|
| 506 | | *****************************************************************************/ |
|---|
| 507 | | static void PacketizeSPU( packetizer_thread_t *p_pack ) |
|---|
| 508 | | { |
|---|
| 509 | | sout_buffer_t *p_out = NULL; |
|---|
| 510 | | pes_packet_t *p_pes; |
|---|
| 511 | | |
|---|
| 512 | | int i_spu_size = 0; |
|---|
| 513 | | |
|---|
| 514 | | for( ;; ) |
|---|
| 515 | | { |
|---|
| 516 | | input_ExtractPES( p_pack->p_fifo, &p_pes ); |
|---|
| 517 | | if( !p_pes ) |
|---|
| 518 | | { |
|---|
| 519 | | p_pack->p_fifo->b_error = 1; |
|---|
| 520 | | return; |
|---|
| 521 | | } |
|---|
| 522 | | #if 0 |
|---|
| 523 | | msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd, |
|---|
| 524 | | p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts ); |
|---|
| 525 | | #endif |
|---|
| 526 | | |
|---|
| 527 | | if( p_out == NULL && |
|---|
| 528 | | ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) ) |
|---|
| 529 | | { |
|---|
| 530 | | msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" ); |
|---|
| 531 | | input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); |
|---|
| 532 | | return; |
|---|
| 533 | | } |
|---|
| 534 | | |
|---|
| 535 | | if( p_pes->i_pes_size > 0 ) |
|---|
| 536 | | { |
|---|
| 537 | | AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes ); |
|---|
| 538 | | |
|---|
| 539 | | if( i_spu_size <= 0 ) |
|---|
| 540 | | { |
|---|
| 541 | | int i_rle; |
|---|
| 542 | | i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1]; |
|---|
| 543 | | i_rle = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4; |
|---|
| 544 | | |
|---|
| 545 | | msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle ); |
|---|
| 546 | | if( i_spu_size == 0 || i_rle >= i_spu_size ) |
|---|
| 547 | | { |
|---|
| 548 | | sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out ); |
|---|
| 549 | | input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); |
|---|
| 550 | | return; |
|---|
| 551 | | } |
|---|
| 552 | | } |
|---|
| 553 | | } |
|---|
| 554 | | |
|---|
| 555 | | input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); |
|---|
| 556 | | |
|---|
| 557 | | if( (int)p_out->i_size >= i_spu_size ) |
|---|
| 558 | | { |
|---|
| 559 | | break; |
|---|
| 560 | | } |
|---|
| 561 | | } |
|---|
| 562 | | msg_Dbg( p_pack->p_fifo, |
|---|
| 563 | | "SPU packets size=%d should be %d", |
|---|
| 564 | | p_out->i_size, i_spu_size ); |
|---|
| 565 | | |
|---|
| 566 | | sout_InputSendBuffer( p_pack->p_sout_input, p_out ); |
|---|
| 567 | | } |
|---|
| 568 | | |
|---|
| 569 | | |
|---|
| 570 | | /***************************************************************************** |
|---|
| 571 | | * End : packetizer thread destruction |
|---|
| 572 | | *****************************************************************************/ |
|---|
| 573 | | static void End ( packetizer_thread_t *p_pack) |
|---|
| 574 | | { |
|---|
| 575 | | if( p_pack->p_sout_input ) |
|---|
| 576 | | { |
|---|
| 577 | | sout_InputDelete( p_pack->p_sout_input ); |
|---|
| 578 | | } |
|---|
| 579 | | free( p_pack ); |
|---|
| 580 | | } |
|---|
| 581 | | |
|---|
| 582 | | /***************************************************************************** |
|---|
| 583 | | * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t. |
|---|
| 584 | | *****************************************************************************/ |
|---|
| 585 | | static void AppendPEStoSoutBuffer( sout_instance_t *p_sout, |
|---|
| 586 | | sout_buffer_t **pp_out, |
|---|
| 587 | | pes_packet_t *p_pes ) |
|---|
| 588 | | { |
|---|
| 589 | | sout_buffer_t *p_out = *pp_out; |
|---|
| 590 | | unsigned int i_out; |
|---|
| 591 | | |
|---|
| 592 | | data_packet_t *p_data; |
|---|
| 593 | | |
|---|
| 594 | | if( p_out == NULL ) |
|---|
| 595 | | { |
|---|
| 596 | | i_out = 0; |
|---|
| 597 | | p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size ); |
|---|
| 598 | | p_out->i_dts = p_pes->i_pts; |
|---|
| 599 | | p_out->i_pts = p_pes->i_pts; |
|---|
| 600 | | } |
|---|
| 601 | | else |
|---|
| 602 | | { |
|---|
| 603 | | i_out = p_out->i_size; |
|---|
| 604 | | sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size ); |
|---|
| 605 | | } |
|---|
| 606 | | p_out->i_size = i_out + p_pes->i_pes_size; |
|---|
| 607 | | |
|---|
| 608 | | for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next) |
|---|
| 609 | | { |
|---|
| 610 | | int i_copy; |
|---|
| 611 | | |
|---|
| 612 | | i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start, |
|---|
| 613 | | p_out->i_size - i_out ); |
|---|
| 614 | | if( i_copy > 0 ) |
|---|
| 615 | | { |
|---|
| 616 | | memcpy( &p_out->p_buffer[i_out], |
|---|
| 617 | | p_data->p_payload_start, |
|---|
| 618 | | i_copy ); |
|---|
| 619 | | } |
|---|
| 620 | | i_out += i_copy; |
|---|
| 621 | | } |
|---|
| 622 | | p_out->i_size = i_out; |
|---|
| 623 | | } |
|---|
| 624 | | |
|---|
| 625 | | /***************************************************************************** |
|---|
| 626 | | * input_ShowPES: Show the next PES in the fifo |
|---|
| 627 | | *****************************************************************************/ |
|---|
| 628 | | static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ) |
|---|
| 629 | | { |
|---|
| 630 | | vlc_mutex_lock( &p_fifo->data_lock ); |
|---|
| 631 | | |
|---|
| 632 | | if( p_fifo->p_first == NULL ) |
|---|
| 633 | | { |
|---|
| 634 | | if( p_fifo->b_die ) |
|---|
| 635 | | { |
|---|
| 636 | | vlc_mutex_unlock( &p_fifo->data_lock ); |
|---|
| 637 | | *pp_pes = NULL; |
|---|
| 638 | | return; |
|---|
| 639 | | } |
|---|
| 640 | | |
|---|
| 641 | | /* Signal the input thread we're waiting. This is only |
|---|
| 642 | | * needed in case of slave clock (ES plug-in) but it won't |
|---|
| 643 | | * harm. */ |
|---|
| 644 | | vlc_cond_signal( &p_fifo->data_wait ); |
|---|
| 645 | | |
|---|
| 646 | | /* Wait for the input to tell us when we received a packet. */ |
|---|
| 647 | | vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); |
|---|
| 648 | | } |
|---|
| 649 | | *pp_pes = p_fifo->p_first; |
|---|
| 650 | | vlc_mutex_unlock( &p_fifo->data_lock ); |
|---|
| 651 | | } |
|---|