]> git.sesse.net Git - vlc/blob - plugins/mpeg_system/mpeg_es.c
861266f286573f083fd42cb4e795732b26fe752c
[vlc] / plugins / mpeg_system / mpeg_es.c
1 /*****************************************************************************
2  * mpeg_es.c : Elementary Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mpeg_es.c,v 1.5 2002/03/15 17:17:35 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>                                              /* strdup() */
29 #include <errno.h>
30
31 #include <videolan/vlc.h>
32
33 #include <sys/types.h>
34
35 #include "stream_control.h"
36 #include "input_ext-intf.h"
37 #include "input_ext-dec.h"
38 #include "input_ext-plugins.h"
39
40 /*****************************************************************************
41  * Constants
42  *****************************************************************************/
43 #define ES_PACKET_SIZE 65536
44 #define MAX_PACKETS_IN_FIFO 3
45
46 /*****************************************************************************
47  * Local prototypes
48  *****************************************************************************/
49 static void input_getfunctions( function_list_t * p_function_list );
50 static int  ESDemux         ( struct input_thread_s * );
51 static int  ESInit          ( struct input_thread_s * );
52 static void ESEnd           ( struct input_thread_s * );
53
54 /*****************************************************************************
55  * Build configuration tree.
56  *****************************************************************************/
57 MODULE_CONFIG_START
58 MODULE_CONFIG_STOP
59
60 MODULE_INIT_START
61     SET_DESCRIPTION( "ISO 13818-2 MPEG Elementary Stream input" )
62     ADD_CAPABILITY( DEMUX, 150 )
63     ADD_SHORTCUT( "es" )
64 MODULE_INIT_STOP
65
66 MODULE_ACTIVATE_START
67     input_getfunctions( &p_module->p_functions->demux );
68 MODULE_ACTIVATE_STOP
69
70 MODULE_DEACTIVATE_START
71 MODULE_DEACTIVATE_STOP
72
73 /*****************************************************************************
74  * Functions exported as capabilities. They are declared as static so that
75  * we don't pollute the namespace too much.
76  *****************************************************************************/
77 static void input_getfunctions( function_list_t * p_function_list )
78 {
79 #define input p_function_list->functions.demux
80     input.pf_init             = ESInit;
81     input.pf_end              = ESEnd;
82     input.pf_demux            = ESDemux;
83     input.pf_rewind           = NULL;
84 #undef input
85 }
86
87 /*
88  * Data reading functions
89  */
90
91 /*****************************************************************************
92  * ESInit: initializes ES structures
93  *****************************************************************************/
94 static int ESInit( input_thread_t * p_input )
95 {
96     es_descriptor_t *   p_es;
97     byte_t *            p_peek;
98
99     /* Initialize access plug-in structures. */
100     if( p_input->i_mtu == 0 )
101     {
102         /* Improve speed. */
103         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
104     }
105
106     /* Have a peep at the show. */
107     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
108     {
109         /* Stream shorter than 4 bytes... */
110         intf_ErrMsg( "input error: cannot peek() (mpeg_es)" );
111         return( -1 );
112     }
113
114     if( *p_peek || *(p_peek + 1) || *(p_peek + 2) != 1 )
115     {
116         if( *p_input->psz_demux && strncmp( p_input->psz_demux, "es", 3 ) )
117         {
118             /* User forced */
119             intf_ErrMsg( "input error: this doesn't seem like an MPEG stream, continuing" );
120         }
121         else
122         {
123             intf_WarnMsg( 2, "input: ES plug-in discarded (no startcode)" );
124             return( -1 );
125         }
126     }
127     else if( *(p_peek + 3) > 0xb9 )
128     {
129         if( *p_input->psz_demux && strncmp( p_input->psz_demux, "es", 3 ) )
130         {
131             /* User forced */
132             intf_ErrMsg( "input error: this seems to be a system stream (PS plug-in ?), but continuing" );
133         }
134         else
135         {
136             intf_WarnMsg( 2, "input: ES plug-in discarded (system startcode)" );
137             return( -1 );
138         }
139     }
140
141     if( input_InitStream( p_input, 0 ) == -1 )
142     {
143         return( -1 );
144     }
145     input_AddProgram( p_input, 0, 0 );
146     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
147     vlc_mutex_lock( &p_input->stream.stream_lock );
148     p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xE0, 0 );
149     p_es->i_stream_id = 0xE0;
150     p_es->i_type = MPEG1_VIDEO_ES;
151     p_es->i_cat = VIDEO_ES;
152     input_SelectES( p_input, p_es );
153     p_input->stream.p_selected_area->i_tell = 0;
154     p_input->stream.p_selected_program->b_is_ok = 1;
155     vlc_mutex_unlock( &p_input->stream.stream_lock );
156
157     return( 0 );
158 }
159
160 /*****************************************************************************
161  * ESEnd: frees unused data
162  *****************************************************************************/
163 static void ESEnd( input_thread_t * p_input )
164 {
165 }
166
167 /*****************************************************************************
168  * ESDemux: reads and demuxes data packets
169  *****************************************************************************
170  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
171  *****************************************************************************/
172 static int ESDemux( input_thread_t * p_input )
173 {
174     ssize_t         i_read;
175     decoder_fifo_t * p_fifo =
176         p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
177     pes_packet_t *  p_pes;
178     data_packet_t * p_data;
179    
180     i_read = input_SplitBuffer( p_input, &p_data, ES_PACKET_SIZE );
181
182     if ( i_read <= 0 )
183     {
184         return( i_read );
185     }
186
187     p_pes = input_NewPES( p_input->p_method_data );
188
189     if( p_pes == NULL )
190     {
191         intf_ErrMsg("Out of memory");
192         input_DeletePacket( p_input->p_method_data, p_data );
193         return( -1 );
194     }
195
196     p_pes->i_rate = p_input->stream.control.i_rate;
197     p_pes->p_first = p_pes->p_last = p_data;
198     p_pes->i_nb_data = 1;
199
200     vlc_mutex_lock( &p_fifo->data_lock );
201     if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
202     {
203         /* Wait for the decoder. */
204         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
205     }
206     vlc_mutex_unlock( &p_fifo->data_lock );
207
208     if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
209          | (input_ClockManageControl( p_input, 
210                       p_input->stream.p_selected_program,
211                          (mtime_t)0 ) == PAUSE_S) )
212     {
213         intf_WarnMsg( 2, "synchro reinit" );
214         p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
215         p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
216     }
217
218     input_DecodePES( p_fifo, p_pes );
219
220     return( 1 );
221 }
222