Changeset 2e3381e626d5cf41d336f3283cc76aaef2654a34
- Timestamp:
- 17/11/03 12:25:54 (5 years ago)
- git-parent:
- Files:
-
- modules/mux/mpeg/ts.c (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
modules/mux/mpeg/ts.c
rccfe579 r2e3381e 3 3 ***************************************************************************** 4 4 * Copyright (C) 2001, 2002 VideoLAN 5 * $Id: ts.c,v 1.3 3 2003/11/07 18:41:09 massiotExp $5 * $Id: ts.c,v 1.34 2003/11/17 11:25:54 fenrir Exp $ 6 6 * 7 7 * Authors: Laurent Aimar <fenrir@via.ecp.fr> … … 102 102 * Local prototypes 103 103 *****************************************************************************/ 104 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR _SOFT( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )104 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT ) 105 105 typedef struct 106 106 { … … 146 146 return b; 147 147 } 148 static inline void BufferChainClean( sout_instance_t *p_sout, sout_buffer_chain_t *c ) 149 { 150 sout_buffer_t *b; 151 152 while( ( b = BufferChainGet( c ) ) ) 153 { 154 sout_BufferDelete( p_sout, b ); 155 } 156 BufferChainInit( c ); 157 } 148 158 149 159 typedef struct ts_stream_s … … 164 174 uint8_t *p_decoder_specific_info; 165 175 166 /* for TS building */ 167 sout_buffer_chain_t chain_ts; 176 sout_buffer_chain_t chain_pes; 177 mtime_t i_pes_dts; 178 mtime_t i_pes_length; 179 int i_pes_used; 168 180 169 181 } ts_stream_t; … … 197 209 int64_t i_bitrate_min; 198 210 int64_t i_bitrate_max; 211 212 int64_t i_caching_delay; 199 213 int64_t i_pcr_delay; 200 int64_t i_pcr_soft_delay; 201 202 mtime_t i_pcr; /* last PCR emited (for pcr-soft) */ 203 mtime_t i_dts; 204 mtime_t i_length; 205 sout_buffer_chain_t chain_ts; 214 215 mtime_t i_pcr; /* last PCR emited */ 206 216 }; 207 217 … … 231 241 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c ); 232 242 233 static int TSFill ( sout_mux_t *, sout_input_t * ); 234 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t *, vlc_bool_t ); 235 static void TSSetDate( sout_buffer_chain_t *, mtime_t, mtime_t, mtime_t ); 236 static void TSSetConstraints( sout_mux_t*, sout_buffer_chain_t *, 237 mtime_t i_length, int i_bitrate_min, int i_bitrate_max ); 243 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr ); 244 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts ); 245 246 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t * ); 238 247 239 248 /***************************************************************************** … … 320 329 p_sys->i_bitrate_max = 0; 321 330 } 322 p_sys->i_pcr_delay = 90000; 331 if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 ) 332 { 333 msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" ); 334 } 335 336 p_sys->i_caching_delay = 200000; 337 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "caching" ) ) ) 338 { 339 p_sys->i_caching_delay = (int64_t)atoi( val ) * 1000; 340 if( p_sys->i_caching_delay <= 0 ) 341 { 342 msg_Err( p_mux, 343 "invalid caching ("I64Fd"ms) reseting to 200ms", 344 p_sys->i_caching_delay / 1000 ); 345 p_sys->i_caching_delay = 200000; 346 } 347 } 348 p_sys->i_pcr_delay = 30000; 323 349 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) ) 324 350 { 325 351 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000; 326 if( p_sys->i_pcr_delay <= 0 ) 352 if( p_sys->i_pcr_delay <= 0 || 353 p_sys->i_pcr_delay >= p_sys->i_caching_delay ) 327 354 { 328 355 msg_Err( p_mux, 329 "invalid pcr delay ("I64Fd"ms) reseting to 90ms",356 "invalid pcr delay ("I64Fd"ms) reseting to 30ms", 330 357 p_sys->i_pcr_delay / 1000 ); 331 p_sys->i_pcr_delay = 90000; 332 } 333 } 334 p_sys->i_pcr_soft_delay = 0; 335 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) ) 336 { 337 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000; 338 if( p_sys->i_pcr_soft_delay <= 0 || 339 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay ) 340 { 341 msg_Err( p_mux, 342 "invalid pcr-soft delay ("I64Fd"ms) disabled", 343 p_sys->i_pcr_soft_delay / 1000 ); 344 p_sys->i_pcr_soft_delay = 0; 345 } 346 } 347 348 msg_Dbg( p_mux, "pcr_delay="I64Fd" pcr_soft_delay="I64Fd, 349 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay ); 358 p_sys->i_pcr_delay = 30000; 359 } 360 } 361 362 msg_Dbg( p_mux, "caching="I64Fd" pcr="I64Fd, 363 p_sys->i_caching_delay, p_sys->i_pcr_delay ); 350 364 351 365 /* for TS generation */ 352 366 p_sys->i_pcr = 0; 353 p_sys->i_dts = 0;354 p_sys->i_length = 0;355 BufferChainInit( &p_sys->chain_ts );356 367 return VLC_SUCCESS; 357 368 } … … 364 375 sout_mux_t *p_mux = (sout_mux_t*)p_this; 365 376 sout_mux_sys_t *p_sys = p_mux->p_sys; 366 sout_buffer_t *p_data;367 377 368 378 msg_Dbg( p_mux, "Close" ); 369 370 /* Empty TS buffer */371 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )372 {373 sout_BufferDelete( p_mux->p_sout, p_data );374 }375 379 376 380 free( p_sys ); … … 504 508 p_input->p_fmt->i_extra_data ); 505 509 } 506 /* Init chain for TS building */ 507 BufferChainInit( &p_stream->chain_ts ); 510 511 /* Init pes chain */ 512 BufferChainInit( &p_stream->chain_pes ); 513 p_stream->i_pes_dts = 0; 514 p_stream->i_pes_length = 0; 515 p_stream->i_pes_used = 0; 508 516 509 517 /* We only change PMT version (PAT isn't changed) */ … … 514 522 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) ) 515 523 { 516 sout_buffer_t *p_data;517 518 524 if( p_sys->p_pcr_input ) 519 525 { 520 526 /* There was already a PCR stream, so clean context */ 521 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys; 522 523 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) ) 524 { 525 sout_BufferDelete( p_mux->p_sout, p_data ); 526 } 527 /* FIXME */ 527 528 } 528 529 p_sys->i_pcr_pid = p_stream->i_pid; 529 530 p_sys->p_pcr_input = p_input; 530 531 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */532 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )533 {534 sout_BufferDelete( p_mux->p_sout, p_data );535 }536 531 } 537 532 … … 546 541 sout_mux_sys_t *p_sys = p_mux->p_sys; 547 542 ts_stream_t *p_stream; 548 sout_buffer_t *p_data;549 543 550 544 msg_Dbg( p_mux, "removing input" ); … … 583 577 { 584 578 /* Empty TS buffer */ 585 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) ) 586 { 587 sout_BufferDelete( p_mux->p_sout, p_data ); 588 } 589 } 590 } 591 592 /* Empty all data in chain_ts */ 593 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) ) 594 { 595 sout_BufferDelete( p_mux->p_sout, p_data ); 596 } 579 /* FIXME */ 580 } 581 } 582 583 /* Empty all data in chain_pes */ 584 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes ); 585 597 586 if( p_stream->p_decoder_specific_info ) 598 587 { … … 607 596 /* We only change PMT version (PAT isn't changed) */ 608 597 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32; 609 610 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */611 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )612 {613 sout_BufferDelete( p_mux->p_sout, p_data );614 }615 598 616 599 return VLC_SUCCESS; … … 625 608 { 626 609 sout_mux_sys_t *p_sys = p_mux->p_sys; 627 628 sout_input_t *p_pcr_input = p_sys->p_pcr_input; 629 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys; 610 ts_stream_t *p_pcr_stream; 630 611 631 612 if( p_sys->i_pcr_pid == 0x1fff ) … … 635 616 return VLC_SUCCESS; 636 617 } 618 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys; 637 619 638 620 for( ;; ) 639 621 { 640 ts_stream_t *p_stream = NULL; 641 sout_buffer_t *p_data; 642 643 int i_stream, i; 644 mtime_t i_dts; 645 646 /* fill ts packets for pcr XXX before GetPAT/GetPMT */ 647 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) ) 648 { 649 /* We need more data */ 650 return VLC_SUCCESS; 651 } 652 653 if( p_sys->chain_ts.p_first == NULL ) 654 { 655 /* Every pcr packet send PAT/PMT */ 656 GetPAT( p_mux, &p_sys->chain_ts); 657 GetPMT( p_mux, &p_sys->chain_ts ); 658 } 659 660 /* search stream with lowest dts */ 661 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ ) 662 { 663 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; 664 665 if( p_stream->chain_ts.p_first == NULL ) 666 { 667 if( TSFill( p_mux, p_mux->pp_inputs[i] ) ) 622 sout_buffer_chain_t chain_ts; 623 int i_packet_count; 624 int i_packet_pos; 625 mtime_t i_pcr_dts; 626 mtime_t i_pcr_length; 627 int i; 628 629 /* 1: get enough PES packet for all input */ 630 for( ;; ) 631 { 632 vlc_bool_t b_ok = VLC_TRUE; 633 sout_buffer_t *p_data; 634 635 /* Accumulate enough data in the pcr stream (>i_caching_delay) */ 636 /* Accumulate enough data in all other stream ( >= length of pcr) */ 637 for( i = 0; i < p_mux->i_nb_inputs; i++ ) 638 { 639 sout_input_t *p_input = p_mux->pp_inputs[i]; 640 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys; 641 642 if( p_stream->i_pes_length <= p_sys->i_caching_delay || 643 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) 668 644 { 669 /* We need more data */ 670 return VLC_SUCCESS; 645 /* Need more data */ 646 if( p_input->p_fifo->i_depth <= 1 ) 647 { 648 if( p_input->p_fmt->i_cat == AUDIO_ES || 649 p_input->p_fmt->i_cat == VIDEO_ES ) 650 { 651 /* We need more data */ 652 return VLC_SUCCESS; 653 } 654 else if( p_input->p_fifo->i_depth <= 0 ) 655 { 656 /* spu, only one packet is needed */ 657 continue; 658 } 659 } 660 b_ok = VLC_FALSE; 661 662 p_data = sout_FifoGet( p_input->p_fifo ); 663 664 if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) || 665 p_data->i_dts < p_stream->i_pes_dts || 666 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) ) 667 { 668 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)", 669 p_data->i_dts, 670 p_stream->i_pes_dts, 671 p_pcr_stream->i_pes_dts ); 672 sout_BufferDelete( p_mux->p_sout, p_data ); 673 674 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes ); 675 p_stream->i_pes_dts = 0; 676 p_stream->i_pes_used = 0; 677 p_stream->i_pes_length = 0; 678 679 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes ); 680 p_pcr_stream->i_pes_dts = 0; 681 p_pcr_stream->i_pes_used = 0; 682 p_pcr_stream->i_pes_length = 0; 683 684 } 685 else 686 { 687 p_stream->i_pes_length += p_data->i_length; 688 if( p_stream->i_pes_dts == 0 ) 689 { 690 p_stream->i_pes_dts = p_data->i_dts; 691 } 692 693 /* Convert to pes */ 694 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 ); 695 696 BufferChainAppend( &p_stream->chain_pes, p_data ); 697 } 671 698 } 672 if( p_stream->chain_ts.p_first == NULL ) 699 } 700 701 if( b_ok ) 702 { 703 break; 704 } 705 } 706 707 /* save */ 708 i_pcr_dts = p_pcr_stream->i_pes_dts; 709 i_pcr_length = p_pcr_stream->i_pes_length; 710 711 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */ 712 /* 2: calculate non accurate total size of muxed ts */ 713 i_packet_count = 0; 714 for( i = 0; i < p_mux->i_nb_inputs; i++ ) 715 { 716 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; 717 sout_buffer_t *p_pes; 718 719 /* False for pcr stream but it will be eough to do PCR algo */ 720 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next ) 721 { 722 int i_size = p_pes->i_size; 723 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) 673 724 { 674 continue; /* SPU_ES */ 725 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts; 726 if( i_frag < 0 ) 727 { 728 /* Next stream */ 729 break; 730 } 731 i_size = p_pes->i_size * i_frag / p_pes->i_length; 675 732 } 676 } 677 678 if( i_stream == -1 || 679 p_stream->chain_ts.p_first->i_dts < i_dts ) 680 { 681 i_stream = i; 682 i_dts = p_stream->chain_ts.p_first->i_dts; 683 } 684 } 685 686 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys; 687 688 p_data = BufferChainGet( &p_stream->chain_ts ); 689 BufferChainAppend( &p_sys->chain_ts, p_data ); 690 691 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL ) 692 { 693 sout_buffer_t *p_ts = p_sys->chain_ts.p_first; 694 695 /* We have consume all TS packets from the PCR stream */ 696 697 if( p_sys->i_length > p_sys->i_pcr_delay ) 698 { 699 /* Send TS data if last PCR was i_pcr_delay ago */ 700 701 if( p_sys->i_bitrate_min > 0 || 702 p_sys->i_bitrate_max > 0 ) 733 i_packet_count += ( i_size + 183 ) / 184; 734 } 735 } 736 /* add overhead for PCR (not really exact) */ 737 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176; 738 739 740 /* 3: mux PES into TS */ 741 BufferChainInit( &chain_ts ); 742 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */ 743 GetPAT( p_mux, &chain_ts); 744 GetPMT( p_mux, &chain_ts ); 745 i_packet_pos = 0; 746 i_packet_count += chain_ts.i_depth; 747 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */ 748 749 for( ;; ) 750 { 751 int i_stream; 752 mtime_t i_dts; 753 ts_stream_t *p_stream; 754 sout_buffer_t *p_ts; 755 vlc_bool_t b_pcr; 756 757 /* Select stream (lowest dts)*/ 758 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ ) 759 { 760 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; 761 762 if( p_stream->i_pes_dts == 0 ) 703 763 { 704 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length, 705 p_sys->i_bitrate_min, p_sys->i_bitrate_max ); 764 continue; 706 765 } 707 766 708 /* Send all data */ 709 TSSetDate( &p_sys->chain_ts, 710 p_sys->i_dts, 711 p_sys->i_length, 712 3 * p_sys->i_pcr_delay/2 ); /* latency is equal to i_pcr_delay 713 3/2 is for security */ 714 sout_AccessOutWrite( p_mux->p_access, p_ts ); 715 716 /* Reset the ts chain */ 717 BufferChainInit( &p_sys->chain_ts ); 718 719 p_sys->i_length = 0; 720 } 721 } 722 } 723 724 return VLC_SUCCESS; 725 } 726 727 728 729 /***************************************************************************** 730 * 731 * 732 *****************************************************************************/ 733 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input ) 734 { 735 sout_mux_sys_t *p_sys = p_mux->p_sys; 736 737 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys; 738 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys; 739 mtime_t i_dts, i_length; 740 sout_buffer_t *p_data; 741 vlc_bool_t b_pcr = VLC_FALSE; 742 vlc_bool_t b_pcr_soft = VLC_FALSE; 743 744 745 for( ;; ) 746 { 747 if( p_input->p_fifo->i_depth <= 1 ) 748 { 749 if( p_input->p_fmt->i_cat == AUDIO_ES || 750 p_input->p_fmt->i_cat == VIDEO_ES ) 751 { 752 /* We need more data */ 753 return VLC_EGENERIC; 754 } 755 else if( p_input->p_fifo->i_depth <= 0 ) 756 { 757 /* spu, only one packet is needed */ 758 return VLC_SUCCESS; 759 } 760 } 761 p_data = sout_FifoGet( p_input->p_fifo ); 762 i_dts = p_data->i_dts; 763 i_length = p_data->i_length; 764 765 if( p_stream->i_pid == p_pcr_stream->i_pid && 766 p_stream->chain_ts.p_first == NULL ) 767 { 768 /* I need that length == dts_next - dts, but be carefull if 769 * some dts are broken length >= 0.5s are suspicious */ 770 sout_buffer_t *p_next; 771 mtime_t i_dts_next; 772 773 p_next = sout_FifoShow( p_input->p_fifo ); 774 i_dts_next = p_next->i_dts; 775 776 if( i_dts_next > i_dts && 777 i_dts_next - i_dts < (mtime_t)500000 ) 778 { 779 i_length = i_dts_next - i_dts; 780 } 781 p_sys->i_length+= i_length; 782 if( p_sys->chain_ts.p_first == NULL ) 783 { 784 p_sys->i_dts = i_dts; 785 p_sys->i_pcr = i_dts; 767 if( i_stream == -1 || 768 p_stream->i_pes_dts < i_dts ) 769 { 770 i_stream = i; 771 i_dts = p_stream->i_pes_dts; 772 } 773 } 774 if( i_stream == -1 ) 775 { 776 break; 777 } 778 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys; 779 780 /* do we need to issue pcr */ 781 b_pcr = VLC_FALSE; 782 if( p_stream == p_pcr_stream && 783 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay ) 784 { 786 785 b_pcr = VLC_TRUE; 787 } 788 else if( p_sys->i_pcr_soft_delay > 0 && 789 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts ) 790 { 791 p_sys->i_pcr = i_dts; 792 b_pcr = VLC_TRUE; 793 b_pcr_soft = VLC_TRUE; 794 } 795 break; 796 } 797 798 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 || 799 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 ) 800 { 801 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting " 802 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts); 803 804 sout_BufferDelete( p_mux->p_sout, p_data ); 805 806 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) ) 807 { 808 sout_BufferDelete( p_mux->p_sout, p_data ); 809 } 810 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) ) 811 { 812 sout_BufferDelete( p_mux->p_sout, p_data ); 813 } 814 return VLC_EGENERIC; 815 } 816 817 if( i_dts >= p_sys->i_dts ) 818 { 819 break; 820 } 821 822 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd 823 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts, 824 p_sys->i_dts + p_sys->i_length - i_dts ); 825 sout_BufferDelete( p_mux->p_sout, p_data ); 826 } 827 828 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1); 829 830 BufferChainInit( &p_stream->chain_ts ); 831 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr ); 832 833 TSSetDate( &p_stream->chain_ts, i_dts, i_length, 0 ); 834 835 if( b_pcr_soft && p_stream->chain_ts.p_first ) 836 { 837 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT; 838 } 839 840 return VLC_SUCCESS; 841 } 842 786 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count; 787 } 788 789 /* Build the TS packet */ 790 p_ts = TSNew( p_mux, p_stream, b_pcr ); 791 i_packet_pos++; 792 793 /* */ 794 BufferChainAppend( &chain_ts, p_ts ); 795 } 796 797 /* 4: date and send */ 798 i_packet_count = chain_ts.i_depth; 799 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */ 800 for( i = 0; i < i_packet_count; i++ ) 801 { 802 sout_buffer_t *p_ts = BufferChainGet( &chain_ts ); 803 804 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count; 805 p_ts->i_length = i_pcr_length / i_packet_count; 806 807 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR ) 808 { 809 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */ 810 TSSetPCR( p_ts, p_ts->i_dts ); 811 } 812 813 /* latency */ 814 p_ts->i_dts += 3*p_sys->i_caching_delay/2; 815 816 sout_AccessOutWrite( p_mux->p_access, p_ts ); 817 } 818 } 819 } 820 821 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr ) 822 { 823 sout_buffer_t *p_pes = p_stream->chain_pes.p_first; 824 sout_buffer_t *p_ts; 825 826 vlc_bool_t b_new_pes = VLC_FALSE; 827 vlc_bool_t b_adaptation_field = VLC_FALSE; 828 829 int i_payload_max = 184 - ( b_pcr ? 8 : 0 ); 830 int i_payload; 831 832 if( p_stream->i_pes_used <= 0 ) 833 { 834 b_new_pes = VLC_TRUE; 835 } 836 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max ); 837 838 if( b_pcr || i_payload < i_payload_max ) 839 { 840 b_adaptation_field = VLC_TRUE; 841 } 842 843 p_ts = sout_BufferNew( p_mux->p_sout, 188 ); 844 845 p_ts->p_buffer[0] = 0x47; 846 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f ); 847 p_ts->p_buffer[2] = p_stream->i_pid & 0xff; 848 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter; 849 850 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16; 851 852 if( b_adaptation_field ) 853 { 854 int i; 855 856 if( b_pcr ) 857 { 858 int i_stuffing = i_payload_max - i_payload; 859 860 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR; 861 862 p_ts->p_buffer[4] = 7 + i_stuffing; 863 p_ts->p_buffer[5] = 0x10; /* flags */ 864 p_ts->p_buffer[6] = ( 0 )&0xff; 865 p_ts->p_buffer[7] = ( 0 )&0xff; 866 p_ts->p_buffer[8] = ( 0 )&0xff; 867 p_ts->p_buffer[9] = ( 0 )&0xff; 868 p_ts->p_buffer[10]= ( 0 )&0x80; 869 p_ts->p_buffer[11]= 0; 870 871 for( i = 12; i < 12 + i_stuffing; i++ ) 872 { 873 p_ts->p_buffer[i] = 0xff; 874 } 875 } 876 else 877 { 878 int i_stuffing = i_payload_max - i_payload; 879 880 p_ts->p_buffer[4] = i_stuffing - 1; 881 if( i_stuffing > 1 ) 882 { 883 p_ts->p_buffer[5] = 0x00; 884 for( i = 6; i < 6 + i_stuffing - 2; i++ ) 885 { 886 p_ts->p_buffer[i] = 0xff; 887 } 888 } 889 } 890 } 891 892 /* copy payload */ 893 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload ); 894 895 p_stream->i_pes_used += i_payload; 896 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size; 897 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size; 898 899 if( p_stream->i_pes_used >= (int)p_pes->i_size ) 900 { 901 p_pes = BufferChainGet( &p_stream->chain_pes ); 902 sout_BufferDelete( p_mux->p_sout, p_pes ); 903 904 p_pes = p_stream->chain_pes.p_first; 905 if( p_pes ) 906 { 907 p_stream->i_pes_dts = p_pes->i_dts; 908 p_stream->i_pes_length = 0; 909 while( p_pes ) 910 { 911 p_stream->i_pes_length += p_pes->i_length; 912 913 p_pes = p_pes->p_next; 914 } 915 } 916 else 917 { 918 p_stream->i_pes_dts = 0; 919 p_stream->i_pes_length = 0; 920 } 921 p_stream->i_pes_used = 0; 922 } 923 924 return p_ts; 925 } 926 927 928 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts ) 929 { 930 mtime_t i_pcr = 9 * p_ts->i_dts / 100; 931 932 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff; 933 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff; 934 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff; 935 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff; 936 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80; 937 } 938 939 #if 0 843 940 static void TSSetConstraints( sout_mux_t *p_mux, sout_buffer_chain_t *c, mtime_t i_length, int i_bitrate_min, int i_bitrate_max ) 844 941 { … … 924 1021 } 925 1022 } 926 927 static void TSSetDate( sout_buffer_chain_t *c, 928 mtime_t i_dts, mtime_t i_length, mtime_t i_send_offset ) 929 { 930 sout_buffer_t *p_ts; 931 mtime_t i_delta = i_length / c->i_depth; 932 int i_packet = 0; 933 934 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next ) 935 { 936 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */ 937 p_ts->i_length = i_delta; 938 939 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT ) 940 { 941 mtime_t i_pcr = 9 * p_ts->i_dts / 100; 942 943 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff; 944 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff; 945 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff; 946 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff; 947 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80; 948 } 949 p_ts->i_dts += i_send_offset; 950 951 i_packet++; 952 } 953 } 1023 #endif 954 1024 955 1025 static void PEStoTS( sout_instance_t *p_sout, 956 1026 sout_buffer_chain_t *c, sout_buffer_t *p_pes, 957 ts_stream_t *p_stream, 958 vlc_bool_t b_pcr ) 1027 ts_stream_t *p_stream ) 959 1028 { 960 1029 uint8_t *p_data; … … 966 1035 p_data = p_pes->p_buffer; 967 1036 968 /* Set pcr only with valid DTS */969 if( p_pes->i_dts <= 0 )970 {971 b_pcr = VLC_FALSE;972 }973 974 1037 b_new_pes = VLC_TRUE; 975 1038 … … 977 1040 { 978 1041 int b_adaptation_field; 979 int i_payload;980 1042 int i_copy; 981 1043 sout_buffer_t *p_ts; … … 993 1055 */ 994 1056 995 i_payload = 184 - ( b_pcr ? 8 : 0 ); 996 i_copy = __MIN( i_size, i_payload ); 997 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE; 1057 i_copy = __MIN( i_size, 184 ); 1058 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE; 998 1059 999 1060 p_ts->p_buffer[0] = 0x47; … … 1009 1070 if( b_adaptation_field ) 1010 1071 { 1072 int i_stuffing = 184 - i_copy; 1011 1073 int i; 1012 1074 1013 if( b_pcr ) 1014 { 1015 mtime_t i_pcr = p_pes->i_dts * 9 / 100; 1016 int i_stuffing = i_payload - i_copy; 1017 1018 p_ts->p_buffer[4] = 7 + i_stuffing; 1019 p_ts->p_buffer[5] = 0x10; /* flags */ 1020 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff; 1021 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff; 1022 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff; 1023 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff; 1024 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80; 1025 p_ts->p_buffer[11]= 0; 1026 1027 b_pcr = VLC_FALSE; 1028 for( i = 12; i < 12 + i_stuffing; i++ ) 1075 p_ts->p_buffer[4] = i_stuffing - 1; 1076 if( i_stuffing > 1 ) 1077 { 1078 p_ts->p_buffer[5] = 0x00; 1079 for( i = 6; i < 6 + i_stuffing - 2; i++ ) 1029 1080 { 1030 1081 p_ts->p_buffer[i] = 0xff; 1031 }1032 }1033 else1034 {1035 int i_stuffing = i_payload - i_copy;1036 1037 p_ts->p_buffer[4] = i_stuffing - 1;1038 if( i_stuffing > 1 )1039 {1040 p_ts->p_buffer[5] = 0x00;1041 for( i = 6; i < 6 + i_stuffing - 2; i++ )1042 {1043 p_ts->p_buffer[i] = 0xff;1044 }1045 1082 } 1046 1083 } … … 1193 1230 p_pat->i_size = bits.i_data; 1194 1231 1195 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat , VLC_FALSE);1232 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat ); 1196 1233 } 1197 1234 … … 1249 1286 p_pmt->i_size = bits.i_data; 1250 1287 1251 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt , VLC_FALSE);1288 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt ); 1252 1289 } 1253 1290 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi … … 1307 1344 p_pat = WritePSISection( p_mux->p_sout, p_section ); 1308 1345 1309 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat , VLC_FALSE);1346 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat ); 1310 1347 1311 1348 dvbpsi_DeletePSISections( p_section ); … … 1513 1550 p_pmt = WritePSISection( p_mux->p_sout, p_section ); 1514 1551 1515 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt , VLC_FALSE);1552 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt ); 1516 1553 1517 1554 dvbpsi_DeletePSISections( p_section );
