/src/vlc/modules/demux/mpeg/mpgv.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * mpgv.c : MPEG-I/II Video demuxer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2004 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * |
8 | | * This program is free software; you can redistribute it and/or modify it |
9 | | * under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation; either version 2.1 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program; if not, write to the Free Software Foundation, |
20 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
21 | | *****************************************************************************/ |
22 | | |
23 | | /***************************************************************************** |
24 | | * Preamble |
25 | | *****************************************************************************/ |
26 | | |
27 | | #ifdef HAVE_CONFIG_H |
28 | | # include "config.h" |
29 | | #endif |
30 | | |
31 | | #include <vlc_common.h> |
32 | | #include <vlc_plugin.h> |
33 | | #include <vlc_demux.h> |
34 | | #include <vlc_codec.h> |
35 | | |
36 | | /***************************************************************************** |
37 | | * Module descriptor |
38 | | *****************************************************************************/ |
39 | | static int Open ( vlc_object_t * ); |
40 | | static void Close( vlc_object_t * ); |
41 | | |
42 | 168 | vlc_module_begin () |
43 | 84 | set_subcategory( SUBCAT_INPUT_DEMUX ) |
44 | 84 | set_description( N_("MPEG-I/II video demuxer" ) ) |
45 | 84 | set_capability( "demux", 7 ) |
46 | 168 | set_callbacks( Open, Close ) |
47 | 84 | add_shortcut( "mpgv" ) |
48 | 84 | vlc_module_end () |
49 | | |
50 | | /***************************************************************************** |
51 | | * Local prototypes |
52 | | *****************************************************************************/ |
53 | | typedef struct |
54 | | { |
55 | | bool b_start; |
56 | | |
57 | | es_out_id_t *p_es; |
58 | | |
59 | | decoder_t *p_packetizer; |
60 | | } demux_sys_t; |
61 | | |
62 | | static int Demux( demux_t * ); |
63 | | static int Control( demux_t *, int, va_list ); |
64 | | |
65 | 1.02k | #define MPGV_PACKET_SIZE 4096 |
66 | | |
67 | | /***************************************************************************** |
68 | | * Close: frees unused data |
69 | | *****************************************************************************/ |
70 | | static void Close( vlc_object_t * p_this ) |
71 | 4 | { |
72 | 4 | demux_t *p_demux = (demux_t*)p_this; |
73 | 4 | demux_sys_t *p_sys = p_demux->p_sys; |
74 | | |
75 | 4 | demux_PacketizerDestroy( p_sys->p_packetizer ); |
76 | 4 | free( p_sys ); |
77 | 4 | } |
78 | | |
79 | | static int CheckMPEGStartCode( const uint8_t *p_peek ) |
80 | 4 | { |
81 | 4 | switch( p_peek[3] ) |
82 | 4 | { |
83 | 1 | case 0x00: |
84 | 1 | if( (p_peek[5] & 0x38) == 0x00 ) |
85 | 0 | return VLC_EGENERIC; |
86 | 1 | break; |
87 | 1 | case 0xB0: |
88 | 0 | case 0xB1: |
89 | 0 | case 0xB6: |
90 | 0 | return VLC_EGENERIC; |
91 | 3 | default: |
92 | 3 | if( p_peek[3] > 0xB9 ) |
93 | 0 | return VLC_EGENERIC; |
94 | 3 | break; |
95 | 4 | } |
96 | 4 | return VLC_SUCCESS; |
97 | 4 | } |
98 | | |
99 | | /***************************************************************************** |
100 | | * Open: initializes demux structures |
101 | | *****************************************************************************/ |
102 | | static int Open( vlc_object_t * p_this ) |
103 | 5 | { |
104 | 5 | demux_t *p_demux = (demux_t*)p_this; |
105 | 5 | demux_sys_t *p_sys; |
106 | 5 | bool b_forced = false; |
107 | | |
108 | 5 | const uint8_t *p_peek; |
109 | | |
110 | 5 | es_format_t fmt; |
111 | | |
112 | 5 | if( vlc_stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) |
113 | 0 | return VLC_EGENERIC; |
114 | | |
115 | 5 | if( p_demux->obj.force ) |
116 | 0 | b_forced = true; |
117 | | |
118 | 5 | if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 ) |
119 | 1 | { |
120 | 1 | if( !b_forced ) return VLC_EGENERIC; |
121 | | |
122 | 0 | msg_Err( p_demux, "this doesn't look like an MPEG ES stream, continuing" ); |
123 | 0 | } |
124 | | |
125 | 4 | if( CheckMPEGStartCode( p_peek ) != VLC_SUCCESS ) |
126 | 0 | { |
127 | 0 | if( !b_forced ) return VLC_EGENERIC; |
128 | 0 | msg_Err( p_demux, "this seems to be a system stream (PS plug-in ?), but continuing" ); |
129 | 0 | } |
130 | 4 | p_demux->pf_demux = Demux; |
131 | 4 | p_demux->pf_control= Control; |
132 | 4 | p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); |
133 | 4 | p_sys->b_start = true; |
134 | 4 | p_sys->p_es = NULL; |
135 | | |
136 | | /* Load the mpegvideo packetizer */ |
137 | 4 | es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_MPGV ); |
138 | 4 | p_sys->p_packetizer = demux_PacketizerNew( VLC_OBJECT(p_demux), &fmt, "mpeg video" ); |
139 | 4 | if( !p_sys->p_packetizer ) |
140 | 0 | { |
141 | 0 | free( p_sys ); |
142 | 0 | return VLC_EGENERIC; |
143 | 0 | } |
144 | | |
145 | | /* create the output */ |
146 | 4 | p_sys->p_es = es_out_Add( p_demux->out, &fmt ); |
147 | 4 | if( p_sys->p_es == NULL ) |
148 | 0 | { |
149 | 0 | Close( p_this ); |
150 | 0 | return VLC_EGENERIC; |
151 | 0 | } |
152 | | |
153 | 4 | return VLC_SUCCESS; |
154 | 4 | } |
155 | | |
156 | | /***************************************************************************** |
157 | | * Demux: reads and demuxes data packets |
158 | | ***************************************************************************** |
159 | | * Returns -1 in case of error, 0 in case of EOF, 1 otherwise |
160 | | *****************************************************************************/ |
161 | | static int Demux( demux_t *p_demux ) |
162 | 1.02k | { |
163 | 1.02k | demux_sys_t *p_sys = p_demux->p_sys; |
164 | 1.02k | block_t *p_block_in, *p_block_out; |
165 | 1.02k | bool b_eof = false; |
166 | | |
167 | 1.02k | if( ( p_block_in = vlc_stream_Block( p_demux->s, MPGV_PACKET_SIZE ) ) == NULL ) |
168 | 4 | { |
169 | 4 | b_eof = true; |
170 | 4 | } |
171 | | |
172 | 1.02k | if( p_block_in ) |
173 | 1.02k | { |
174 | 1.02k | p_block_in->i_pts = |
175 | 1.02k | p_block_in->i_dts = ( p_sys->b_start ) ? VLC_TICK_0 : VLC_TICK_INVALID; |
176 | 1.02k | } |
177 | | |
178 | 1.03k | while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, |
179 | 1.03k | p_block_in ? &p_block_in : NULL )) ) |
180 | 4 | { |
181 | 4 | p_sys->b_start = false; |
182 | | |
183 | 8 | while( p_block_out ) |
184 | 4 | { |
185 | 4 | block_t *p_next = p_block_out->p_next; |
186 | | |
187 | 4 | es_out_SetPCR( p_demux->out, p_block_out->i_dts ); |
188 | | |
189 | 4 | p_block_out->p_next = NULL; |
190 | 4 | es_out_Send( p_demux->out, p_sys->p_es, p_block_out ); |
191 | | |
192 | 4 | p_block_out = p_next; |
193 | 4 | } |
194 | 4 | } |
195 | 1.02k | return (b_eof) ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS; |
196 | 1.02k | } |
197 | | |
198 | | /***************************************************************************** |
199 | | * Control: |
200 | | *****************************************************************************/ |
201 | | static int Control( demux_t *p_demux, int i_query, va_list args ) |
202 | 0 | { |
203 | | /* demux_sys_t *p_sys = p_demux->p_sys; */ |
204 | | /* FIXME calculate the bitrate */ |
205 | 0 | if( i_query == DEMUX_SET_TIME ) |
206 | 0 | return VLC_EGENERIC; |
207 | 0 | else |
208 | 0 | return demux_vaControlHelper( p_demux->s, |
209 | 0 | 0, -1, |
210 | 0 | 0, 1, i_query, args ); |
211 | 0 | } |
212 | | |