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 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_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
= (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
)
278 p_stream
->i_stream_id
=
279 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
280 p_stream
->i_stream_type
= 0x02; /* ISO/IEC 13818 Video */
283 p_stream
->i_stream_id
=
284 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
285 p_stream
->i_stream_type
= 0x10;
288 p_stream
->i_stream_id
=
289 StreamIdGet( p_sys
->stream_id_mpgv
, 0xe0, 0xef );
290 p_stream
->i_stream_type
= 0x1b;
292 case VLC_CODEC_DVD_LPCM
:
293 p_stream
->i_stream_id
=
294 0xbd00 | StreamIdGet( p_sys
->stream_id_lpcm
, 0xa0, 0xaf );
297 p_stream
->i_stream_id
=
298 0xbd00 | StreamIdGet( p_sys
->stream_id_dts
, 0x88, 0x8f );
301 p_stream
->i_stream_id
=
302 0xbd00 | StreamIdGet( p_sys
->stream_id_a52
, 0x80, 0x87 );
305 p_stream
->i_stream_id
=
306 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
307 p_stream
->i_stream_type
= 0x03; /* ISO/IEC 11172 Audio */
310 p_stream
->i_stream_id
=
311 StreamIdGet( p_sys
->stream_id_mpga
, 0xc0, 0xcf );
312 p_stream
->i_stream_type
= 0x0f;
315 p_stream
->i_stream_id
=
316 0xbd00 | StreamIdGet( p_sys
->stream_id_spu
, 0x20, 0x3f );
322 if( p_stream
->i_stream_id
< 0 ) goto error
;
324 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
326 p_sys
->i_audio_bound
++;
327 p_stream
->i_max_buff_size
= 4 * 1024;
329 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
331 p_sys
->i_video_bound
++;
332 p_stream
->i_max_buff_size
= 400 * 1024; /* FIXME -- VCD uses 46, SVCD
333 uses 230, ffmpeg has 230 with a note that it is small */
336 { /* FIXME -- what's valid for not audio or video? */
337 p_stream
->i_max_buff_size
= 4 * 1024;
340 /* Try to set a sensible default value for the instant bitrate */
341 p_sys
->i_instant_bitrate
+= p_input
->p_fmt
->i_bitrate
+ 1000/* overhead */;
343 /* FIXME -- spec requires an upper limit rate boundary in the system header;
344 our codecs are VBR; using 2x nominal rate, convert to 50 bytes/sec */
345 p_sys
->i_rate_bound
+= p_input
->p_fmt
->i_bitrate
* 2 / (8 * 50);
346 p_sys
->i_psm_version
++;
348 p_stream
->lang
[0] = p_stream
->lang
[1] = p_stream
->lang
[2] = 0;
349 if( p_input
->p_fmt
->psz_language
)
351 char *psz
= p_input
->p_fmt
->psz_language
;
352 const iso639_lang_t
*pl
= NULL
;
354 if( strlen( psz
) == 2 )
356 pl
= GetLang_1( psz
);
358 else if( strlen( psz
) == 3 )
360 pl
= GetLang_2B( psz
);
361 if( !strcmp( pl
->psz_iso639_1
, "??" ) )
363 pl
= GetLang_2T( psz
);
366 if( pl
&& strcmp( pl
->psz_iso639_1
, "??" ) )
368 p_stream
->lang
[0] = pl
->psz_iso639_2T
[0];
369 p_stream
->lang
[1] = pl
->psz_iso639_2T
[1];
370 p_stream
->lang
[2] = pl
->psz_iso639_2T
[2];
372 msg_Dbg( p_mux
, " - lang=%c%c%c",
373 p_stream
->lang
[0], p_stream
->lang
[1], p_stream
->lang
[2] );
383 /*****************************************************************************
385 *****************************************************************************/
386 static int DelStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
388 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
389 ps_stream_t
*p_stream
=(ps_stream_t
*)p_input
->p_sys
;
391 msg_Dbg( p_mux
, "removing input" );
392 switch( p_input
->p_fmt
->i_codec
)
395 StreamIdRelease( p_sys
->stream_id_mpgv
, 0xe0,
396 p_stream
->i_stream_id
);
398 case VLC_CODEC_DVD_LPCM
:
399 StreamIdRelease( p_sys
->stream_id_lpcm
, 0xa0,
400 p_stream
->i_stream_id
&0xff );
403 StreamIdRelease( p_sys
->stream_id_dts
, 0x88,
404 p_stream
->i_stream_id
&0xff );
407 StreamIdRelease( p_sys
->stream_id_a52
, 0x80,
408 p_stream
->i_stream_id
&0xff );
411 StreamIdRelease( p_sys
->stream_id_mpga
, 0xc0,
412 p_stream
->i_stream_id
);
415 StreamIdRelease( p_sys
->stream_id_spu
, 0x20,
416 p_stream
->i_stream_id
&0xff );
423 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
425 p_sys
->i_audio_bound
--;
427 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
429 p_sys
->i_video_bound
--;
432 /* Try to set a sensible default value for the instant bitrate */
433 p_sys
->i_instant_bitrate
-= (p_input
->p_fmt
->i_bitrate
+ 1000);
434 /* rate_bound is in units of 50 bytes/second */
435 p_sys
->i_rate_bound
-= (p_input
->p_fmt
->i_bitrate
* 2)/(8 * 50);
437 p_sys
->i_psm_version
++;
443 /*****************************************************************************
444 * Mux: Call each time there is new data for at least one stream
445 *****************************************************************************/
446 static int Mux( sout_mux_t
*p_mux
)
448 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
452 sout_input_t
*p_input
;
453 ps_stream_t
*p_stream
;
455 block_t
*p_ps
, *p_data
;
459 /* Choose which stream to mux */
460 int i_stream
= sout_MuxGetStream( p_mux
, 1, &i_dts
);
466 p_input
= p_mux
->pp_inputs
[i_stream
];
467 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
470 /* Write regulary PackHeader */
471 if( p_sys
->i_pes_count
% 30 == 0)
473 /* Update the instant bitrate every second or so */
474 if( p_sys
->i_instant_size
&&
475 i_dts
- p_sys
->i_instant_dts
> 1000000 )
477 int64_t i_instant_bitrate
= p_sys
->i_instant_size
* 8000000 /
478 ( i_dts
- p_sys
->i_instant_dts
);
480 p_sys
->i_instant_bitrate
+= i_instant_bitrate
;
481 p_sys
->i_instant_bitrate
/= 2;
483 p_sys
->i_instant_size
= 0;
484 p_sys
->i_instant_dts
= i_dts
;
486 else if( !p_sys
->i_instant_size
)
488 p_sys
->i_instant_dts
= i_dts
;
491 MuxWritePackHeader( p_mux
, &p_ps
, i_dts
);
494 /* Write regulary SystemHeader */
495 if( p_sys
->i_pes_count
% 300 == 0 )
499 MuxWriteSystemHeader( p_mux
, &p_ps
, i_dts
);
501 /* For MPEG1 streaming, set HEADER flag */
502 for( p_pk
= p_ps
; p_pk
!= NULL
; p_pk
= p_pk
->p_next
)
504 p_pk
->i_flags
|= BLOCK_FLAG_HEADER
;
508 /* Write regulary ProgramStreamMap */
509 if( p_sys
->b_mpeg2
&& p_sys
->i_pes_count
% 300 == 0 )
511 MuxWritePSM( p_mux
, &p_ps
, i_dts
);
514 /* Get and mux a packet */
515 p_data
= block_FifoGet( p_input
->p_fifo
);
516 EStoPES ( &p_data
, p_data
, p_input
->p_fmt
, p_stream
->i_stream_id
,
517 p_sys
->b_mpeg2
, 0, 0, p_sys
->i_pes_max_size
);
519 block_ChainAppend( &p_ps
, p_data
);
521 /* Get size of output data so we can calculate the instant bitrate */
522 for( p_data
= p_ps
; p_data
; p_data
= p_data
->p_next
)
524 p_sys
->i_instant_size
+= p_data
->i_buffer
;
527 sout_AccessOutWrite( p_mux
->p_access
, p_ps
);
529 /* Increase counter */
530 p_sys
->i_pes_count
++;
536 /*****************************************************************************
538 *****************************************************************************/
539 static void StreamIdInit( bool *id
, int i_range
)
543 for( i
= 0; i
< i_range
; i
++ )
548 static int StreamIdGet( bool *id
, int i_id_min
, int i_id_max
)
552 for( i
= 0; i
<= i_id_max
- i_id_min
; i
++ )
563 static void StreamIdRelease( bool *id
, int i_id_min
, int i_id
)
565 id
[i_id
- i_id_min
] = true;
568 static void MuxWritePackHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
571 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
577 i_scr
= (i_dts
- p_sys
->i_dts_delay
) * 9 / 100;
579 p_hdr
= block_Alloc( 18 );
580 p_hdr
->i_pts
= p_hdr
->i_dts
= i_dts
;
581 bits_initwrite( &bits
, 14, p_hdr
->p_buffer
);
582 bits_write( &bits
, 32, 0x01ba );
584 /* The spec specifies that the mux rate must be rounded upwards */
585 i_mux_rate
= (p_sys
->i_instant_bitrate
+ 8 * 50 - 1 ) / (8 * 50);
589 bits_write( &bits
, 2, 0x01 );
593 bits_write( &bits
, 4, 0x02 );
596 bits_write( &bits
, 3, ( i_scr
>> 30 )&0x07 );
597 bits_write( &bits
, 1, 1 ); // marker
598 bits_write( &bits
, 15, ( i_scr
>> 15 )&0x7fff );
599 bits_write( &bits
, 1, 1 ); // marker
600 bits_write( &bits
, 15, i_scr
&0x7fff );
601 bits_write( &bits
, 1, 1 ); // marker
605 bits_write( &bits
, 9, 0 ); // src extension
607 bits_write( &bits
, 1, 1 ); // marker
609 bits_write( &bits
, 22, i_mux_rate
);
610 bits_write( &bits
, 1, 1 ); // marker
614 bits_write( &bits
, 1, 1 ); // marker
615 bits_write( &bits
, 5, 0x1f ); // reserved
616 bits_write( &bits
, 3, 0 ); // stuffing bytes
619 p_hdr
->i_buffer
= p_sys
->b_mpeg2
? 14: 12;
621 block_ChainAppend( p_buf
, p_hdr
);
624 static void MuxWriteSystemHeader( sout_mux_t
*p_mux
, block_t
**p_buf
,
627 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
633 int i_nb_private
, i_nb_stream
;
636 /* Count the number of private stream */
637 for( i
= 0, i_nb_private
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
639 ps_stream_t
*p_stream
;
641 p_stream
= (ps_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
;
643 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
649 /* Private stream are declared only one time */
650 i_nb_stream
= p_mux
->i_nb_inputs
-
651 ( i_nb_private
> 0 ? i_nb_private
- 1 : 0 );
653 p_hdr
= block_Alloc( 12 + i_nb_stream
* 3 );
654 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
656 /* The spec specifies that the reported rate_bound must be upper limit */
657 i_rate_bound
= (p_sys
->i_rate_bound
);
659 bits_initwrite( &bits
, 12 + i_nb_stream
* 3, p_hdr
->p_buffer
);
660 bits_write( &bits
, 32, 0x01bb );
661 bits_write( &bits
, 16, 12 - 6 + i_nb_stream
* 3 );
662 bits_write( &bits
, 1, 1 ); // marker bit
663 bits_write( &bits
, 22, i_rate_bound
);
664 bits_write( &bits
, 1, 1 ); // marker bit
666 bits_write( &bits
, 6, p_sys
->i_audio_bound
);
667 bits_write( &bits
, 1, 0 ); // fixed flag
668 bits_write( &bits
, 1, 0 ); // CSPS flag
669 bits_write( &bits
, 1, 0 ); // system audio lock flag
670 bits_write( &bits
, 1, 0 ); // system video lock flag
672 bits_write( &bits
, 1, 1 ); // marker bit
674 bits_write( &bits
, 5, p_sys
->i_video_bound
);
675 bits_write( &bits
, 1, 1 ); // packet rate restriction flag (1 for mpeg1)
676 bits_write( &bits
, 7, 0xff ); // reserved bits
678 /* stream_id table */
679 for( i
= 0, b_private
= false; i
< p_mux
->i_nb_inputs
; i
++ )
681 sout_input_t
*p_input
;
682 ps_stream_t
*p_stream
;
684 p_input
= p_mux
->pp_inputs
[i
];
685 p_stream
= (ps_stream_t
*)p_input
->p_sys
;
687 if( ( p_stream
->i_stream_id
&0xff00 ) == 0xbd00 )
694 /* Write stream id */
695 bits_write( &bits
, 8, 0xbd );
699 /* Write stream id */
700 bits_write( &bits
, 8, p_stream
->i_stream_id
&0xff );
703 bits_write( &bits
, 2, 0x03 ); /* reserved */
704 if( p_input
->p_fmt
->i_cat
== AUDIO_ES
)
706 bits_write( &bits
, 1, 0 );
707 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
709 else if( p_input
->p_fmt
->i_cat
== VIDEO_ES
)
711 bits_write( &bits
, 1, 1 );
712 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 1024);
716 /* FIXME -- the scale of 0 means do a /128 */
717 bits_write( &bits
, 1, 0 );
718 bits_write( &bits
, 13, p_stream
->i_max_buff_size
/ 128 );
722 block_ChainAppend( p_buf
, p_hdr
);
725 static void MuxWritePSM( sout_mux_t
*p_mux
, block_t
**p_buf
, mtime_t i_dts
)
727 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
730 int i
, i_psm_size
= 16, i_es_map_size
= 0;
732 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
734 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
735 ps_stream_t
*p_stream
= p_input
->p_sys
;
738 if( p_stream
->lang
[0] != 0 ) i_es_map_size
+= 6;
741 i_psm_size
+= i_es_map_size
;
743 p_hdr
= block_Alloc( i_psm_size
);
744 p_hdr
->i_dts
= p_hdr
->i_pts
= i_dts
;
746 memset( p_hdr
->p_buffer
, 0, p_hdr
->i_buffer
);
747 bits_initwrite( &bits
, i_psm_size
, p_hdr
->p_buffer
);
748 bits_write( &bits
, 32, 0x01bc );
749 bits_write( &bits
, 16, i_psm_size
- 6 );
750 bits_write( &bits
, 1, 1 ); /* current_next_indicator */
751 bits_write( &bits
, 2, 0xF ); /* reserved */
752 bits_write( &bits
, 5, p_sys
->i_psm_version
);
753 bits_write( &bits
, 7, 0xFF ); /* reserved */
754 bits_write( &bits
, 1, 1 ); /* marker */
756 bits_write( &bits
, 16, 0 ); /* program_stream_info_length */
759 bits_write( &bits
, 16, i_es_map_size
); /* elementary_stream_map_length */
760 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
762 sout_input_t
*p_input
= p_mux
->pp_inputs
[i
];
763 ps_stream_t
*p_stream
= p_input
->p_sys
;
765 bits_write( &bits
, 8, p_stream
->i_stream_type
); /* stream_type */
766 bits_write( &bits
, 8, p_stream
->i_stream_id
); /* elementary_stream_id */
768 /* ISO639 language descriptor */
769 if( p_stream
->lang
[0] != 0 )
771 bits_write( &bits
, 16, 6 ); /* elementary_stream_info_length */
773 bits_write( &bits
, 8, 0x0a ); /* descriptor_tag */
774 bits_write( &bits
, 8, 4 ); /* descriptor_length */
776 bits_write( &bits
, 8, p_stream
->lang
[0] );
777 bits_write( &bits
, 8, p_stream
->lang
[1] );
778 bits_write( &bits
, 8, p_stream
->lang
[2] );
779 bits_write( &bits
, 8, 0 ); /* audio type: 0x00 undefined */
783 bits_write( &bits
, 16, 0 ); /* elementary_stream_info_length */
789 uint32_t i_crc
= 0xffffffff;
790 for( i
= 0; (size_t)i
< p_hdr
->i_buffer
; i
++ )
791 i_crc
= (i_crc
<< 8) ^
792 p_sys
->crc32_table
[((i_crc
>> 24) ^ p_hdr
->p_buffer
[i
]) & 0xff];
794 bits_write( &bits
, 32, i_crc
);
797 block_ChainAppend( p_buf
, p_hdr
);