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 the VideoLAN team
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
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 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 General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, 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 int 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_New( p_mux
, 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
= (bool*)va_arg( args
, bool * );
242 case MUX_GET_ADD_STREAM_WAIT
:
243 pb_bool
= (bool*)va_arg( args
, bool * );
248 ppsz
= (char**)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 p_stream
->i_stream_type
= 0x81;
272 /* Init this new stream */
273 switch( p_input
->p_fmt
->i_codec
)
276 p_stream
->i_stream_id
=
277 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
278 p_stream
->i_stream_type
= 0x02; /* ISO/IEC 13818 Video */
281 p_stream
->i_stream_id
=
282 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
283 p_stream
->i_stream_type
= 0x10;
286 p_stream
->i_stream_id
=
287 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
288 p_stream
->i_stream_type
= 0x1b;
290 case VLC_CODEC_DVD_LPCM
:
291 p_stream
->i_stream_id
=
292 0xbd00 | StreamIdGet( p_sys
->stream_id_lpcm
, 0xa0, 0xaf );
295 p_stream
->i_stream_id
=
296 0xbd00 | StreamIdGet( p_sys
->stream_id_dts
, 0x88, 0x8f );
299 p_stream
->i_stream_id
=
300 0xbd00 | StreamIdGet( p_sys
->stream_id_a52
, 0x80, 0x87 );
303 p_stream
->i_stream_id
=
304 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
305 p_stream
->i_stream_type
= 0x03; /* ISO/IEC 11172 Audio */
308 p_stream
->i_stream_id
=
309 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
310 p_stream
->i_stream_type
= 0x0f;
313 p_stream
->i_stream_id
=
314 0xbd00 | StreamIdGet( p_sys
->stream_id_spu
, 0x20, 0x3f );
320 if( p_stream
->i_stream_id
< 0 ) goto error
;
322 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
324 p_sys
->i_audio_bound
++;
325 p_stream
->i_max_buff_size
= 4 * 1024;
327 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
329 p_sys
->i_video_bound
++;
330 p_stream
->i_max_buff_size
= 400 * 1024; /* FIXME -- VCD uses 46, SVCD
331 uses 230, ffmpeg has 230 with a note that it is small */
334 { /* FIXME -- what's valid for not audio or video? */
335 p_stream
->i_max_buff_size
= 4 * 1024;
338 /* Try to set a sensible default value for the instant bitrate */
339 p_sys
->i_instant_bitrate
+= p_input
->p_fmt
->i_bitrate
+ 1000/* overhead */;
341 /* FIXME -- spec requires an upper limit rate boundary in the system header;
342 our codecs are VBR; using 2x nominal rate, convert to 50 bytes/sec */
343 p_sys
->i_rate_bound
+= p_input
->p_fmt
->i_bitrate
* 2 / (8 * 50);
344 p_sys
->i_psm_version
++;
346 p_stream
->lang
[0] = p_stream
->lang
[1] = p_stream
->lang
[2] = 0;
347 if( p_input
->p_fmt
->psz_language
)
349 char *psz
= p_input
->p_fmt
->psz_language
;
350 const iso639_lang_t
*pl
= NULL
;
352 if( strlen( psz
) == 2 )
354 pl
= GetLang_1( psz
);
356 else if( strlen( psz
) == 3 )
358 pl
= GetLang_2B( psz
);
359 if( !strcmp( pl
->psz_iso639_1
, "??" ) )
361 pl
= GetLang_2T( psz
);
364 if( pl
&& strcmp( pl
->psz_iso639_1
, "??" ) )
366 p_stream
->lang
[0] = pl
->psz_iso639_2T
[0];
367 p_stream
->lang
[1] = pl
->psz_iso639_2T
[1];
368 p_stream
->lang
[2] = pl
->psz_iso639_2T
[2];
370 msg_Dbg( p_mux
, " - lang=%c%c%c",
371 p_stream
->lang
[0], p_stream
->lang
[1], p_stream
->lang
[2] );
381 /*****************************************************************************
383 *****************************************************************************/
384 static int DelStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
386 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
387 ps_stream_t
*p_stream
=(ps_stream_t
*)p_input
->p_sys
;
389 msg_Dbg( p_mux
, "removing input" );
390 switch( p_input
->p_fmt
->i_codec
)
393 StreamIdRelease( p_sys
->stream_id_mpgv
, 0xe0,
394 p_stream
->i_stream_id
);
396 case VLC_CODEC_DVD_LPCM
:
397 StreamIdRelease( p_sys
->stream_id_lpcm
, 0xa0,
398 p_stream
->i_stream_id
&0xff );
401 StreamIdRelease( p_sys
->stream_id_dts
, 0x88,
402 p_stream
->i_stream_id
&0xff );
405 StreamIdRelease( p_sys
->stream_id_a52
, 0x80,
406 p_stream
->i_stream_id
&0xff );
409 StreamIdRelease( p_sys
->stream_id_mpga
, 0xc0,
410 p_stream
->i_stream_id
);
413 StreamIdRelease( p_sys
->stream_id_spu
, 0x20,
414 p_stream
->i_stream_id
&0xff );
421 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
423 p_sys
->i_audio_bound
--;
425 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
427 p_sys
->i_video_bound
--;
430 /* Try to set a sensible default value for the instant bitrate */
431 p_sys
->i_instant_bitrate
-= (p_input
->p_fmt
->i_bitrate
+ 1000);
432 /* rate_bound is in units of 50 bytes/second */
433 p_sys
->i_rate_bound
-= (p_input
->p_fmt
->i_bitrate
* 2)/(8 * 50);
435 p_sys
->i_psm_version
++;
441 /*****************************************************************************
442 * Mux: Call each time there is new data for at least one stream
443 *****************************************************************************/
444 static int Mux( sout_mux_t
*p_mux
)
446 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
450 sout_input_t
*p_input
;
451 ps_stream_t
*p_stream
;
453 block_t
*p_ps
, *p_data
;
457 /* Choose which stream to mux */
458 int i_stream
= sout_MuxGetStream( p_mux
, 1, &i_dts
);
464 p_input
= p_mux
->pp_inputs
[i_stream
];
465 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
468 /* Write regulary PackHeader */
469 if( p_sys
->i_pes_count
% 30 == 0)
471 /* Update the instant bitrate every second or so */
472 if( p_sys
->i_instant_size
&&
473 i_dts
- p_sys
->i_instant_dts
> 1000000 )
475 int64_t i_instant_bitrate
= p_sys
->i_instant_size
* 8000000 /
476 ( i_dts
- p_sys
->i_instant_dts
);
478 p_sys
->i_instant_bitrate
+= i_instant_bitrate
;
479 p_sys
->i_instant_bitrate
/= 2;
481 p_sys
->i_instant_size
= 0;
482 p_sys
->i_instant_dts
= i_dts
;
484 else if( !p_sys
->i_instant_size
)
486 p_sys
->i_instant_dts
= i_dts
;
489 MuxWritePackHeader( p_mux
, &p_ps
, i_dts
);
492 /* Write regulary SystemHeader */
493 if( p_sys
->i_pes_count
% 300 == 0 )
497 MuxWriteSystemHeader( p_mux
, &p_ps
, i_dts
);
499 /* For MPEG1 streaming, set HEADER flag */
500 for( p_pk
= p_ps
; p_pk
!= NULL
; p_pk
= p_pk
->p_next
)
502 p_pk
->i_flags
|= BLOCK_FLAG_HEADER
;
506 /* Write regulary ProgramStreamMap */
507 if( p_sys
->b_mpeg2
&& p_sys
->i_pes_count
% 300 == 0 )
509 MuxWritePSM( p_mux
, &p_ps
, i_dts
);
512 /* Get and mux a packet */
513 p_data
= block_FifoGet( p_input
->p_fifo
);
514 EStoPES ( p_mux
->p_sout
, &p_data
, p_data
,
515 p_input
->p_fmt
, p_stream
->i_stream_id
,
516 p_sys
->b_mpeg2
, 0, 0, p_sys
->i_pes_max_size
);
518 block_ChainAppend( &p_ps
, p_data
);
520 /* Get size of output data so we can calculate the instant bitrate */
521 for( p_data
= p_ps
; p_data
; p_data
= p_data
->p_next
)
523 p_sys
->i_instant_size
+= p_data
->i_buffer
;
526 sout_AccessOutWrite( p_mux
->p_access
, p_ps
);
528 /* Increase counter */
529 p_sys
->i_pes_count
++;
535 /*****************************************************************************
537 *****************************************************************************/
538 static void StreamIdInit( bool *id
, int i_range
)
542 for( i
= 0; i
< i_range
; i
++ )
547 static int StreamIdGet( bool *id
, int i_id_min
, int i_id_max
)
551 for( i
= 0; i
<= i_id_max
- i_id_min
; i
++ )
562 static void StreamIdRelease( bool *id
, int i_id_min
, int i_id
)
564 id
[i_id
- i_id_min
] = true;
567 static void MuxWritePackHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
570 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
576 i_scr
= (i_dts
- p_sys
->i_dts_delay
) * 9 / 100;
578 p_hdr
= block_New( p_mux
, 18 );
579 p_hdr
->i_pts
= p_hdr
->i_dts
= i_dts
;
580 bits_initwrite( &bits
, 14, p_hdr
->p_buffer
);
581 bits_write( &bits
, 32, 0x01ba );
583 /* The spec specifies that the mux rate must be rounded upwards */
584 i_mux_rate
= (p_sys
->i_instant_bitrate
+ 8 * 50 - 1 ) / (8 * 50);
588 bits_write( &bits
, 2, 0x01 );
592 bits_write( &bits
, 4, 0x02 );
595 bits_write( &bits
, 3, ( i_scr
>> 30 )&0x07 );
596 bits_write( &bits
, 1, 1 ); // marker
597 bits_write( &bits
, 15, ( i_scr
>> 15 )&0x7fff );
598 bits_write( &bits
, 1, 1 ); // marker
599 bits_write( &bits
, 15, i_scr
&0x7fff );
600 bits_write( &bits
, 1, 1 ); // marker
604 bits_write( &bits
, 9, 0 ); // src extension
606 bits_write( &bits
, 1, 1 ); // marker
608 bits_write( &bits
, 22, i_mux_rate
);
609 bits_write( &bits
, 1, 1 ); // marker
613 bits_write( &bits
, 1, 1 ); // marker
614 bits_write( &bits
, 5, 0x1f ); // reserved
615 bits_write( &bits
, 3, 0 ); // stuffing bytes
618 p_hdr
->i_buffer
= p_sys
->b_mpeg2
? 14: 12;
620 block_ChainAppend( p_buf
, p_hdr
);
623 static void MuxWriteSystemHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
626 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
632 int i_nb_private
, i_nb_stream
;
635 /* Count the number of private stream */
636 for( i
= 0, i_nb_private
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
638 ps_stream_t
*p_stream
;
640 p_stream
= (ps_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
;
642 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
648 /* Private stream are declared only one time */
649 i_nb_stream
= p_mux
->i_nb_inputs
-
650 ( i_nb_private
> 0 ? i_nb_private
- 1 : 0 );
652 p_hdr
= block_New( p_mux
, 12 + i_nb_stream
* 3 );
653 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
655 /* The spec specifies that the reported rate_bound must be upper limit */
656 i_rate_bound
= (p_sys
->i_rate_bound
);
658 bits_initwrite( &bits
, 12 + i_nb_stream
* 3, p_hdr
->p_buffer
);
659 bits_write( &bits
, 32, 0x01bb );
660 bits_write( &bits
, 16, 12 - 6 + i_nb_stream
* 3 );
661 bits_write( &bits
, 1, 1 ); // marker bit
662 bits_write( &bits
, 22, i_rate_bound
);
663 bits_write( &bits
, 1, 1 ); // marker bit
665 bits_write( &bits
, 6, p_sys
->i_audio_bound
);
666 bits_write( &bits
, 1, 0 ); // fixed flag
667 bits_write( &bits
, 1, 0 ); // CSPS flag
668 bits_write( &bits
, 1, 0 ); // system audio lock flag
669 bits_write( &bits
, 1, 0 ); // system video lock flag
671 bits_write( &bits
, 1, 1 ); // marker bit
673 bits_write( &bits
, 5, p_sys
->i_video_bound
);
674 bits_write( &bits
, 1, 1 ); // packet rate restriction flag (1 for mpeg1)
675 bits_write( &bits
, 7, 0xff ); // reserved bits
677 /* stream_id table */
678 for( i
= 0, b_private
= false; i
< p_mux
->i_nb_inputs
; i
++ )
680 sout_input_t
*p_input
;
681 ps_stream_t
*p_stream
;
683 p_input
= p_mux
->pp_inputs
[i
];
684 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
686 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
693 /* Write stream id */
694 bits_write( &bits
, 8, 0xbd );
698 /* Write stream id */
699 bits_write( &bits
, 8, p_stream
->i_stream_id
&0xff );
702 bits_write( &bits
, 2, 0x03 ); /* reserved */
703 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
705 bits_write( &bits
, 1, 0 );
706 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
708 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
710 bits_write( &bits
, 1, 1 );
711 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 1024);
715 /* FIXME -- the scale of 0 means do a /128 */
716 bits_write( &bits
, 1, 0 );
717 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
721 block_ChainAppend( p_buf
, p_hdr
);
724 static void MuxWritePSM( sout_mux_t
*p_mux
, block_t
**p_buf
, mtime_t i_dts
)
726 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
729 int i
, i_psm_size
= 16, i_es_map_size
= 0;
731 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
733 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
734 ps_stream_t
*p_stream
= p_input
->p_sys
;
737 if( p_stream
->lang
[0] != 0 ) i_es_map_size
+= 6;
740 i_psm_size
+= i_es_map_size
;
742 p_hdr
= block_New( p_mux
, i_psm_size
);
743 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
745 memset( p_hdr
->p_buffer
, 0, p_hdr
->i_buffer
);
746 bits_initwrite( &bits
, i_psm_size
, p_hdr
->p_buffer
);
747 bits_write( &bits
, 32, 0x01bc );
748 bits_write( &bits
, 16, i_psm_size
- 6 );
749 bits_write( &bits
, 1, 1 ); /* current_next_indicator */
750 bits_write( &bits
, 2, 0xF ); /* reserved */
751 bits_write( &bits
, 5, p_sys
->i_psm_version
);
752 bits_write( &bits
, 7, 0xFF ); /* reserved */
753 bits_write( &bits
, 1, 1 ); /* marker */
755 bits_write( &bits
, 16, 0 ); /* program_stream_info_length */
758 bits_write( &bits
, 16, i_es_map_size
); /* elementary_stream_map_length */
759 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
761 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
762 ps_stream_t
*p_stream
= p_input
->p_sys
;
764 bits_write( &bits
, 8, p_stream
->i_stream_type
); /* stream_type */
765 bits_write( &bits
, 8, p_stream
->i_stream_id
); /* elementary_stream_id */
767 /* ISO639 language descriptor */
768 if( p_stream
->lang
[0] != 0 )
770 bits_write( &bits
, 16, 6 ); /* elementary_stream_info_length */
772 bits_write( &bits
, 8, 0x0a ); /* descriptor_tag */
773 bits_write( &bits
, 8, 4 ); /* descriptor_length */
775 bits_write( &bits
, 8, p_stream
->lang
[0] );
776 bits_write( &bits
, 8, p_stream
->lang
[1] );
777 bits_write( &bits
, 8, p_stream
->lang
[2] );
778 bits_write( &bits
, 8, 0 ); /* audio type: 0x00 undefined */
782 bits_write( &bits
, 16, 0 ); /* elementary_stream_info_length */
788 uint32_t i_crc
= 0xffffffff;
789 for( i
= 0; (size_t)i
< p_hdr
->i_buffer
; i
++ )
790 i_crc
= (i_crc
<< 8) ^
791 p_sys
->crc32_table
[((i_crc
>> 24) ^ p_hdr
->p_buffer
[i
]) & 0xff];
793 bits_write( &bits
, 32, i_crc
);
796 block_ChainAppend( p_buf
, p_hdr
);