1 /*****************************************************************************
2 * ps.c: MPEG PS (ISO/IEC 13818-1) / MPEG SYSTEM (ISO/IEC 1172-1)
3 * multiplexer module for vlc
4 *****************************************************************************
5 * Copyright (C) 2001, 2002 VLC authors and VideoLAN
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * Eric Petit <titer@videolan.org>
10 * Gildas Bazin <gbazin@videolan.org>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
38 #include <vlc_block.h>
43 #include <vlc_iso_lang.h>
45 /*****************************************************************************
47 *****************************************************************************/
48 #define DTS_TEXT N_("DTS delay (ms)")
49 #define DTS_LONGTEXT N_("Delay the DTS (decoding time " \
50 "stamps) and PTS (presentation timestamps) of the data in the " \
51 "stream, compared to the SCRs. This allows for some buffering inside " \
52 "the client decoder.")
54 #define PES_SIZE_TEXT N_("PES maximum size")
55 #define PES_SIZE_LONGTEXT N_("Set the maximum allowed PES "\
56 "size when producing the MPEG PS streams.")
58 static int Open ( vlc_object_t
* );
59 static void Close ( vlc_object_t
* );
61 #define SOUT_CFG_PREFIX "sout-ps-"
64 set_description( N_("PS muxer") )
65 set_shortname( "MPEG-PS" )
66 set_category( CAT_SOUT
)
67 set_subcategory( SUBCAT_SOUT_MUX
)
68 set_capability( "sout mux", 50 )
69 add_shortcut( "ps", "mpeg1", "dvd" )
70 set_callbacks( Open
, Close
)
72 add_integer( SOUT_CFG_PREFIX
"dts-delay", 200, DTS_TEXT
,
74 add_integer( SOUT_CFG_PREFIX
"pes-max-size", PES_PAYLOAD_SIZE_MAX
,
75 PES_SIZE_TEXT
, PES_SIZE_LONGTEXT
, true )
78 /*****************************************************************************
80 *****************************************************************************/
81 static int Control ( sout_mux_t
*, int, va_list );
82 static int AddStream( sout_mux_t
*, sout_input_t
* );
83 static void DelStream( sout_mux_t
*, sout_input_t
* );
84 static int Mux ( sout_mux_t
* );
86 /*****************************************************************************
88 *****************************************************************************/
90 static void MuxWritePackHeader ( sout_mux_t
*, block_t
**, mtime_t
);
91 static void MuxWriteSystemHeader( sout_mux_t
*, block_t
**, mtime_t
);
92 static void MuxWritePSM ( sout_mux_t
*, block_t
**, mtime_t
);
94 static void StreamIdInit ( bool *id
, int i_range
);
95 static int StreamIdGet ( bool *id
, int i_id_min
, int i_id_max
);
96 static void StreamIdRelease ( bool *id
, int i_id_min
, int i_id
);
98 typedef struct ps_stream_s
102 int i_max_buff_size
; /* used in system header */
104 /* Language is iso639-2T */
109 struct sout_mux_sys_t
111 /* Which id are unused */
112 bool stream_id_mpga
[16]; /* 0xc0 -> 0xcf */
113 bool stream_id_mpgv
[16]; /* 0xe0 -> 0xef */
114 bool stream_id_a52
[8]; /* 0x80 -> 0x87 <- FIXME I'm not sure */
115 bool stream_id_spu
[32]; /* 0x20 -> 0x3f */
116 bool stream_id_dts
[8]; /* 0x88 -> 0x8f */
117 bool stream_id_lpcm
[16]; /* 0xa0 -> 0xaf */
124 int i_rate_bound
; /* units of 50 bytes/second */
126 int64_t i_instant_bitrate
;
127 int64_t i_instant_size
;
128 int64_t i_instant_dts
;
135 uint32_t crc32_table
[256];
138 static const char *const ppsz_sout_options
[] = {
139 "dts-delay", "pes-max-size", NULL
142 /*****************************************************************************
144 *****************************************************************************/
145 static int Open( vlc_object_t
*p_this
)
147 sout_mux_t
*p_mux
= (sout_mux_t
*)p_this
;
148 sout_mux_sys_t
*p_sys
;
151 msg_Info( p_mux
, "Open" );
152 config_ChainParse( p_mux
, SOUT_CFG_PREFIX
, ppsz_sout_options
, p_mux
->p_cfg
);
154 p_mux
->pf_control
= Control
;
155 p_mux
->pf_addstream
= AddStream
;
156 p_mux
->pf_delstream
= DelStream
;
158 p_mux
->p_sys
= p_sys
= malloc( sizeof( sout_mux_sys_t
) );
160 /* Init free stream id */
161 StreamIdInit( p_sys
->stream_id_a52
, 8 );
162 StreamIdInit( p_sys
->stream_id_dts
, 8 );
163 StreamIdInit( p_sys
->stream_id_mpga
, 16 );
164 StreamIdInit( p_sys
->stream_id_mpgv
, 16 );
165 StreamIdInit( p_sys
->stream_id_lpcm
, 16 );
166 StreamIdInit( p_sys
->stream_id_spu
, 32 );
168 p_sys
->i_audio_bound
= 0;
169 p_sys
->i_video_bound
= 0;
170 p_sys
->i_system_header
= 0;
171 p_sys
->i_pes_count
= 0;
173 p_sys
->i_psm_version
= 0;
175 p_sys
->i_instant_bitrate
= 0;
176 p_sys
->i_instant_size
= 0;
177 p_sys
->i_instant_dts
= 0;
178 p_sys
->i_rate_bound
= 0;
179 p_sys
->b_mpeg2
= !(p_mux
->psz_mux
&& !strcmp( p_mux
->psz_mux
, "mpeg1" ));
181 var_Get( p_mux
, SOUT_CFG_PREFIX
"dts-delay", &val
);
182 p_sys
->i_dts_delay
= (int64_t)val
.i_int
* 1000;
184 var_Get( p_mux
, SOUT_CFG_PREFIX
"pes-max-size", &val
);
185 p_sys
->i_pes_max_size
= (int64_t)val
.i_int
;
187 /* Initialise CRC32 table */
192 for( i
= 0; i
< 256; i
++ )
195 for( j
= (i
<< 24) | 0x800000; j
!= 0x80000000; j
<<= 1 )
196 k
= (k
<< 1) ^ (((k
^ j
) & 0x80000000) ? 0x04c11db7 : 0);
198 p_sys
->crc32_table
[i
] = k
;
205 /*****************************************************************************
207 *****************************************************************************/
208 static void Close( vlc_object_t
* p_this
)
210 sout_mux_t
*p_mux
= (sout_mux_t
*)p_this
;
211 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
215 msg_Info( p_mux
, "Close" );
217 p_end
= block_Alloc( 4 );
218 p_end
->p_buffer
[0] = 0x00; p_end
->p_buffer
[1] = 0x00;
219 p_end
->p_buffer
[2] = 0x01; p_end
->p_buffer
[3] = 0xb9;
221 sout_AccessOutWrite( p_mux
->p_access
, p_end
);
226 /*****************************************************************************
228 *****************************************************************************/
229 static int Control( sout_mux_t
*p_mux
, int i_query
, va_list args
)
237 case MUX_CAN_ADD_STREAM_WHILE_MUXING
:
238 pb_bool
= va_arg( args
, bool * );
242 case MUX_GET_ADD_STREAM_WAIT
:
243 pb_bool
= va_arg( args
, bool * );
248 ppsz
= va_arg( args
, char ** );
249 *ppsz
= strdup( "video/mpeg" );
257 /*****************************************************************************
259 *****************************************************************************/
260 static int AddStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
262 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
263 ps_stream_t
*p_stream
;
266 msg_Dbg( p_mux
, "adding input codec=%4.4s",
267 (char*)&p_input
->p_fmt
->i_codec
);
269 p_input
->p_sys
= p_stream
= malloc( sizeof( ps_stream_t
) );
270 if( unlikely(p_input
->p_sys
== NULL
) )
272 p_stream
->i_stream_type
= 0x81;
274 /* Init this new stream */
275 switch( p_input
->p_fmt
->i_codec
)
280 p_stream
->i_stream_id
=
281 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
282 p_stream
->i_stream_type
= 0x02; /* ISO/IEC 13818 Video */
285 p_stream
->i_stream_id
=
286 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
287 p_stream
->i_stream_type
= 0x10;
290 p_stream
->i_stream_id
=
291 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
292 p_stream
->i_stream_type
= 0x1b;
294 case VLC_CODEC_DVD_LPCM
:
295 p_stream
->i_stream_id
=
296 0xbd00 | StreamIdGet( p_sys
->stream_id_lpcm
, 0xa0, 0xaf );
299 p_stream
->i_stream_id
=
300 0xbd00 | StreamIdGet( p_sys
->stream_id_dts
, 0x88, 0x8f );
303 p_stream
->i_stream_id
=
304 0xbd00 | StreamIdGet( p_sys
->stream_id_a52
, 0x80, 0x87 );
307 p_stream
->i_stream_id
=
308 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
309 p_stream
->i_stream_type
= 0x03; /* ISO/IEC 11172 Audio */
312 p_stream
->i_stream_id
=
313 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
314 p_stream
->i_stream_type
= 0x0f;
317 p_stream
->i_stream_id
=
318 0xbd00 | StreamIdGet( p_sys
->stream_id_spu
, 0x20, 0x3f );
324 if( p_stream
->i_stream_id
< 0 ) goto error
;
326 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
328 p_sys
->i_audio_bound
++;
329 p_stream
->i_max_buff_size
= 4 * 1024;
331 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
333 p_sys
->i_video_bound
++;
334 p_stream
->i_max_buff_size
= 400 * 1024; /* FIXME -- VCD uses 46, SVCD
335 uses 230, ffmpeg has 230 with a note that it is small */
338 { /* FIXME -- what's valid for not audio or video? */
339 p_stream
->i_max_buff_size
= 4 * 1024;
342 /* Try to set a sensible default value for the instant bitrate */
343 p_sys
->i_instant_bitrate
+= p_input
->p_fmt
->i_bitrate
+ 1000/* overhead */;
345 /* FIXME -- spec requires an upper limit rate boundary in the system header;
346 our codecs are VBR; using 2x nominal rate, convert to 50 bytes/sec */
347 p_sys
->i_rate_bound
+= p_input
->p_fmt
->i_bitrate
* 2 / (8 * 50);
348 p_sys
->i_psm_version
++;
350 p_stream
->lang
[0] = p_stream
->lang
[1] = p_stream
->lang
[2] = 0;
351 if( p_input
->p_fmt
->psz_language
)
353 char *psz
= p_input
->p_fmt
->psz_language
;
354 const iso639_lang_t
*pl
= NULL
;
356 if( strlen( psz
) == 2 )
358 pl
= GetLang_1( psz
);
360 else if( strlen( psz
) == 3 )
362 pl
= GetLang_2B( psz
);
363 if( !strcmp( pl
->psz_iso639_1
, "??" ) )
365 pl
= GetLang_2T( psz
);
368 if( pl
&& strcmp( pl
->psz_iso639_1
, "??" ) )
370 p_stream
->lang
[0] = pl
->psz_iso639_2T
[0];
371 p_stream
->lang
[1] = pl
->psz_iso639_2T
[1];
372 p_stream
->lang
[2] = pl
->psz_iso639_2T
[2];
374 msg_Dbg( p_mux
, " - lang=%c%c%c",
375 p_stream
->lang
[0], p_stream
->lang
[1], p_stream
->lang
[2] );
385 /*****************************************************************************
387 *****************************************************************************/
388 static void DelStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
390 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
391 ps_stream_t
*p_stream
=(ps_stream_t
*)p_input
->p_sys
;
393 msg_Dbg( p_mux
, "removing input" );
394 switch( p_input
->p_fmt
->i_codec
)
397 StreamIdRelease( p_sys
->stream_id_mpgv
, 0xe0,
398 p_stream
->i_stream_id
);
400 case VLC_CODEC_DVD_LPCM
:
401 StreamIdRelease( p_sys
->stream_id_lpcm
, 0xa0,
402 p_stream
->i_stream_id
&0xff );
405 StreamIdRelease( p_sys
->stream_id_dts
, 0x88,
406 p_stream
->i_stream_id
&0xff );
409 StreamIdRelease( p_sys
->stream_id_a52
, 0x80,
410 p_stream
->i_stream_id
&0xff );
413 StreamIdRelease( p_sys
->stream_id_mpga
, 0xc0,
414 p_stream
->i_stream_id
);
417 StreamIdRelease( p_sys
->stream_id_spu
, 0x20,
418 p_stream
->i_stream_id
&0xff );
425 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
427 p_sys
->i_audio_bound
--;
429 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
431 p_sys
->i_video_bound
--;
434 /* Try to set a sensible default value for the instant bitrate */
435 p_sys
->i_instant_bitrate
-= (p_input
->p_fmt
->i_bitrate
+ 1000);
436 /* rate_bound is in units of 50 bytes/second */
437 p_sys
->i_rate_bound
-= (p_input
->p_fmt
->i_bitrate
* 2)/(8 * 50);
439 p_sys
->i_psm_version
++;
444 /*****************************************************************************
445 * Mux: Call each time there is new data for at least one stream
446 *****************************************************************************/
447 static int Mux( sout_mux_t
*p_mux
)
449 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
453 sout_input_t
*p_input
;
454 ps_stream_t
*p_stream
;
456 block_t
*p_ps
, *p_data
;
460 /* Choose which stream to mux */
461 int i_stream
= sout_MuxGetStream( p_mux
, 1, &i_dts
);
467 p_input
= p_mux
->pp_inputs
[i_stream
];
468 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
471 /* Write regulary PackHeader */
472 if( p_sys
->i_pes_count
% 30 == 0)
474 /* Update the instant bitrate every second or so */
475 if( p_sys
->i_instant_size
&&
476 i_dts
- p_sys
->i_instant_dts
> 1000000 )
478 int64_t i_instant_bitrate
= p_sys
->i_instant_size
* 8000000 /
479 ( i_dts
- p_sys
->i_instant_dts
);
481 p_sys
->i_instant_bitrate
+= i_instant_bitrate
;
482 p_sys
->i_instant_bitrate
/= 2;
484 p_sys
->i_instant_size
= 0;
485 p_sys
->i_instant_dts
= i_dts
;
487 else if( !p_sys
->i_instant_size
)
489 p_sys
->i_instant_dts
= i_dts
;
492 MuxWritePackHeader( p_mux
, &p_ps
, i_dts
);
495 /* Write regulary SystemHeader */
496 if( p_sys
->i_pes_count
% 300 == 0 )
500 MuxWriteSystemHeader( p_mux
, &p_ps
, i_dts
);
502 /* For MPEG1 streaming, set HEADER flag */
503 for( p_pk
= p_ps
; p_pk
!= NULL
; p_pk
= p_pk
->p_next
)
505 p_pk
->i_flags
|= BLOCK_FLAG_HEADER
;
509 /* Write regulary ProgramStreamMap */
510 if( p_sys
->b_mpeg2
&& p_sys
->i_pes_count
% 300 == 0 )
512 MuxWritePSM( p_mux
, &p_ps
, i_dts
);
515 /* Get and mux a packet */
516 p_data
= block_FifoGet( p_input
->p_fifo
);
517 EStoPES ( &p_data
, p_input
->p_fmt
, p_stream
->i_stream_id
,
518 p_sys
->b_mpeg2
, 0, 0, p_sys
->i_pes_max_size
, 0 );
520 block_ChainAppend( &p_ps
, p_data
);
522 /* Get size of output data so we can calculate the instant bitrate */
523 for( p_data
= p_ps
; p_data
; p_data
= p_data
->p_next
)
525 p_sys
->i_instant_size
+= p_data
->i_buffer
;
528 sout_AccessOutWrite( p_mux
->p_access
, p_ps
);
530 /* Increase counter */
531 p_sys
->i_pes_count
++;
537 /*****************************************************************************
539 *****************************************************************************/
540 static void StreamIdInit( bool *id
, int i_range
)
544 for( i
= 0; i
< i_range
; i
++ )
549 static int StreamIdGet( bool *id
, int i_id_min
, int i_id_max
)
553 for( i
= 0; i
<= i_id_max
- i_id_min
; i
++ )
564 static void StreamIdRelease( bool *id
, int i_id_min
, int i_id
)
566 id
[i_id
- i_id_min
] = true;
569 static void MuxWritePackHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
572 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
578 i_scr
= (i_dts
- p_sys
->i_dts_delay
) * 9 / 100;
580 p_hdr
= block_Alloc( 18 );
581 p_hdr
->i_pts
= p_hdr
->i_dts
= i_dts
;
582 bits_initwrite( &bits
, 14, p_hdr
->p_buffer
);
583 bits_write( &bits
, 32, 0x01ba );
585 /* The spec specifies that the mux rate must be rounded upwards */
586 i_mux_rate
= (p_sys
->i_instant_bitrate
+ 8 * 50 - 1 ) / (8 * 50);
590 bits_write( &bits
, 2, 0x01 );
594 bits_write( &bits
, 4, 0x02 );
597 bits_write( &bits
, 3, ( i_scr
>> 30 )&0x07 );
598 bits_write( &bits
, 1, 1 ); // marker
599 bits_write( &bits
, 15, ( i_scr
>> 15 )&0x7fff );
600 bits_write( &bits
, 1, 1 ); // marker
601 bits_write( &bits
, 15, i_scr
&0x7fff );
602 bits_write( &bits
, 1, 1 ); // marker
606 bits_write( &bits
, 9, 0 ); // src extension
608 bits_write( &bits
, 1, 1 ); // marker
610 bits_write( &bits
, 22, i_mux_rate
);
611 bits_write( &bits
, 1, 1 ); // marker
615 bits_write( &bits
, 1, 1 ); // marker
616 bits_write( &bits
, 5, 0x1f ); // reserved
617 bits_write( &bits
, 3, 0 ); // stuffing bytes
620 p_hdr
->i_buffer
= p_sys
->b_mpeg2
? 14: 12;
622 block_ChainAppend( p_buf
, p_hdr
);
625 static void MuxWriteSystemHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
628 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
634 int i_nb_private
, i_nb_stream
;
637 /* Count the number of private stream */
638 for( i
= 0, i_nb_private
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
640 ps_stream_t
*p_stream
;
642 p_stream
= (ps_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
;
644 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
650 /* Private stream are declared only one time */
651 i_nb_stream
= p_mux
->i_nb_inputs
-
652 ( i_nb_private
> 0 ? i_nb_private
- 1 : 0 );
654 p_hdr
= block_Alloc( 12 + i_nb_stream
* 3 );
655 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
657 /* The spec specifies that the reported rate_bound must be upper limit */
658 i_rate_bound
= (p_sys
->i_rate_bound
);
660 bits_initwrite( &bits
, 12 + i_nb_stream
* 3, p_hdr
->p_buffer
);
661 bits_write( &bits
, 32, 0x01bb );
662 bits_write( &bits
, 16, 12 - 6 + i_nb_stream
* 3 );
663 bits_write( &bits
, 1, 1 ); // marker bit
664 bits_write( &bits
, 22, i_rate_bound
);
665 bits_write( &bits
, 1, 1 ); // marker bit
667 bits_write( &bits
, 6, p_sys
->i_audio_bound
);
668 bits_write( &bits
, 1, 0 ); // fixed flag
669 bits_write( &bits
, 1, 0 ); // CSPS flag
670 bits_write( &bits
, 1, 0 ); // system audio lock flag
671 bits_write( &bits
, 1, 0 ); // system video lock flag
673 bits_write( &bits
, 1, 1 ); // marker bit
675 bits_write( &bits
, 5, p_sys
->i_video_bound
);
676 bits_write( &bits
, 1, 1 ); // packet rate restriction flag (1 for mpeg1)
677 bits_write( &bits
, 7, 0xff ); // reserved bits
679 /* stream_id table */
680 for( i
= 0, b_private
= false; i
< p_mux
->i_nb_inputs
; i
++ )
682 sout_input_t
*p_input
;
683 ps_stream_t
*p_stream
;
685 p_input
= p_mux
->pp_inputs
[i
];
686 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
688 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
695 /* Write stream id */
696 bits_write( &bits
, 8, 0xbd );
700 /* Write stream id */
701 bits_write( &bits
, 8, p_stream
->i_stream_id
&0xff );
704 bits_write( &bits
, 2, 0x03 ); /* reserved */
705 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
707 bits_write( &bits
, 1, 0 );
708 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
710 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
712 bits_write( &bits
, 1, 1 );
713 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 1024);
717 /* FIXME -- the scale of 0 means do a /128 */
718 bits_write( &bits
, 1, 0 );
719 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
723 block_ChainAppend( p_buf
, p_hdr
);
726 static void MuxWritePSM( sout_mux_t
*p_mux
, block_t
**p_buf
, mtime_t i_dts
)
728 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
731 int i
, i_psm_size
= 16, i_es_map_size
= 0;
733 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
735 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
736 ps_stream_t
*p_stream
= p_input
->p_sys
;
739 if( p_stream
->lang
[0] != 0 ) i_es_map_size
+= 6;
742 i_psm_size
+= i_es_map_size
;
744 p_hdr
= block_Alloc( i_psm_size
);
745 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
747 memset( p_hdr
->p_buffer
, 0, p_hdr
->i_buffer
);
748 bits_initwrite( &bits
, i_psm_size
, p_hdr
->p_buffer
);
749 bits_write( &bits
, 32, 0x01bc );
750 bits_write( &bits
, 16, i_psm_size
- 6 );
751 bits_write( &bits
, 1, 1 ); /* current_next_indicator */
752 bits_write( &bits
, 2, 0xF ); /* reserved */
753 bits_write( &bits
, 5, p_sys
->i_psm_version
);
754 bits_write( &bits
, 7, 0xFF ); /* reserved */
755 bits_write( &bits
, 1, 1 ); /* marker */
757 bits_write( &bits
, 16, 0 ); /* program_stream_info_length */
760 bits_write( &bits
, 16, i_es_map_size
); /* elementary_stream_map_length */
761 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
763 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
764 ps_stream_t
*p_stream
= p_input
->p_sys
;
766 bits_write( &bits
, 8, p_stream
->i_stream_type
); /* stream_type */
767 bits_write( &bits
, 8, p_stream
->i_stream_id
); /* elementary_stream_id */
769 /* ISO639 language descriptor */
770 if( p_stream
->lang
[0] != 0 )
772 bits_write( &bits
, 16, 6 ); /* elementary_stream_info_length */
774 bits_write( &bits
, 8, 0x0a ); /* descriptor_tag */
775 bits_write( &bits
, 8, 4 ); /* descriptor_length */
777 bits_write( &bits
, 8, p_stream
->lang
[0] );
778 bits_write( &bits
, 8, p_stream
->lang
[1] );
779 bits_write( &bits
, 8, p_stream
->lang
[2] );
780 bits_write( &bits
, 8, 0 ); /* audio type: 0x00 undefined */
784 bits_write( &bits
, 16, 0 ); /* elementary_stream_info_length */
790 uint32_t i_crc
= 0xffffffff;
791 for( i
= 0; (size_t)i
< p_hdr
->i_buffer
; i
++ )
792 i_crc
= (i_crc
<< 8) ^
793 p_sys
->crc32_table
[((i_crc
>> 24) ^ p_hdr
->p_buffer
[i
]) & 0xff];
795 bits_write( &bits
, 32, i_crc
);
798 block_ChainAppend( p_buf
, p_hdr
);