]> git.sesse.net Git - vlc/blob - modules/mux/mpeg/pes.c
Added stream output. (common work with titer).
[vlc] / modules / mux / mpeg / pes.c
1 /*****************************************************************************
2  * pes.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: pes.c,v 1.1 2002/12/14 21:32:41 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <fcntl.h>
34
35 #include <vlc/vlc.h>
36 #include <vlc/input.h>
37 #include <vlc/sout.h>
38
39 #ifdef HAVE_UNISTD_H
40 #   include <unistd.h>
41 #elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
42 #   include <io.h>
43 #endif
44
45 #include "codecs.h"
46 #include "pes.h"
47 #include "bits.h"
48
49 int EStoPES( sout_instance_t *p_sout,
50              sout_buffer_t **pp_pes,
51              sout_buffer_t *p_es,
52              int i_stream_id,
53              int b_mpeg2 )
54 {
55     sout_buffer_t *p_pes;
56     bits_buffer_t bits;
57     mtime_t i_pts, i_dts;
58     uint8_t *p_data;
59     int     i_size;
60
61     i_pts = p_es->i_pts * 9 / 100; // 90000 units clock
62     i_dts = p_es->i_dts * 9 / 100; // 90000 units clock
63
64     i_size = p_es->i_size;
65     p_data = p_es->p_buffer;
66
67     *pp_pes = p_pes = NULL;
68
69     do
70     {
71         int     i_copy;
72
73         i_copy = __MIN( i_size, 65500 );
74
75         if( *pp_pes == NULL )
76         {
77             *pp_pes = p_pes = sout_BufferNew( p_sout, 100 + i_copy);
78             p_pes->i_dts = p_es->i_dts;
79             p_pes->i_pts = p_es->i_pts;
80             p_pes->i_length = p_es->i_length;
81         }
82         else
83         {
84             p_pes->p_next = sout_BufferNew( p_sout, 100 + i_copy );
85             p_pes = p_pes->p_next;
86
87             p_pes->i_dts    = 0;
88             p_pes->i_pts    = 0;
89             p_pes->i_length = 0;
90         }
91
92         p_pes->i_size = 0;
93
94
95         bits_initwrite( &bits, 100, p_pes->p_buffer );
96
97         /* first 4 bytes common pes header */
98             /* add start code for pes 0x000001 */
99         bits_write( &bits, 24, 0x01 );
100             /* add stream id */
101         bits_write( &bits, 8, i_stream_id );
102
103         switch( i_stream_id )
104         {
105             case PES_PROGRAM_STREAM_MAP:
106             case PES_PADDING:
107             case PES_PRIVATE_STREAM_2:
108             case PES_ECM:
109             case PES_EMM:
110             case PES_PROGRAM_STREAM_DIRECTORY:
111             case PES_DSMCC_STREAM:
112             case PES_ITU_T_H222_1_TYPE_E_STREAM:
113                 /* add pes data size  */
114                 bits_write( &bits, 16, i_copy );
115                 bits_align( &bits );
116                 break;
117
118             default:
119                 /* arg, a little more difficult */
120                 if( b_mpeg2 )
121                 {
122                     int     i_pts_dts;
123
124                     if( i_dts > 0 )
125                     {
126                         bits_write( &bits, 16, i_copy  + 13 );
127                         i_pts_dts = 0x03;
128                     }
129                     else
130                     {
131                         bits_write( &bits, 16, i_copy  + 8 );
132                         i_pts_dts = 0x02;
133                     }
134
135                     bits_write( &bits, 2, 0x02 ); // mpeg2 id
136                     bits_write( &bits, 2, 0x00 ); // pes scrambling control
137                     bits_write( &bits, 1, 0x00 ); // pes priority
138                     bits_write( &bits, 1, 0x00 ); // data alignement indicator
139                     bits_write( &bits, 1, 0x00 ); // copyright
140                     bits_write( &bits, 1, 0x00 ); // original or copy
141
142                     bits_write( &bits, 2, i_pts_dts ); // pts_dts flags
143                     bits_write( &bits, 1, 0x00 ); // escr flags
144                     bits_write( &bits, 1, 0x00 ); // es rate flag
145                     bits_write( &bits, 1, 0x00 ); // dsm trick mode flag
146                     bits_write( &bits, 1, 0x00 ); // additional copy info flag
147                     bits_write( &bits, 1, 0x00 ); // pes crc flag
148                     bits_write( &bits, 1, 0x00 ); // pes extention flags
149                     if( i_pts_dts & 0x01 )
150                     {
151                         bits_write( &bits, 8, 0x0a ); // header size -> pts and dts
152                     }
153                     else
154                     {
155                         bits_write( &bits, 8, 0x05 ); // header size -> pts
156                     }
157
158                     /* write pts */
159                     bits_write( &bits, 4, i_pts_dts ); // '0010' or '0011'
160                     bits_write( &bits, 3, i_pts >> 30 );
161                     bits_write( &bits, 1, 0x01 ); // marker
162                     bits_write( &bits, 15, i_pts >> 15 );
163                     bits_write( &bits, 1, 0x01 ); // marker
164                     bits_write( &bits, 15, i_pts );
165                     bits_write( &bits, 1, 0x01 ); // marker
166
167                     /* write i_dts */
168                     if( i_pts_dts & 0x01 )
169                     {
170                         bits_write( &bits, 4, 0x01 ); // '0001'
171                         bits_write( &bits, 3, i_dts >> 30 );
172                         bits_write( &bits, 1, 0x01 ); // marker
173                         bits_write( &bits, 15, i_dts >> 15 );
174                         bits_write( &bits, 1, 0x01 ); // marker
175                         bits_write( &bits, 15, i_dts );
176                         bits_write( &bits, 1, 0x01 ); // marker
177
178                         i_dts = 0; // write dts only once
179                     }
180
181                 }
182                 else
183                 {
184                     msg_Warn( p_sout, "es isn't mpeg2 -->corrupted pes" );
185                 }
186                 /* now should be stuffing */
187                 /* and then pes data */
188
189                 bits_align( &bits );
190                 break;
191         }
192
193         if( i_copy > 0 )
194         {
195             memcpy( p_pes->p_buffer + bits.i_data, p_data, i_copy );
196         }
197
198         i_size -= i_copy;
199         p_data += i_copy;
200         p_pes->i_size = bits.i_data + i_copy;
201
202
203     } while( i_size > 0 );
204
205     sout_BufferDelete( p_sout, p_es );
206     return( 0 );
207 }
208