/src/vlc/modules/demux/vc1.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * vc1.c : VC1 Video demuxer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2002-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 | | #define FPS_TEXT N_("Frames per Second") |
43 | | #define FPS_LONGTEXT N_("Desired frame rate for the VC-1 stream.") |
44 | | |
45 | 116 | vlc_module_begin () |
46 | 58 | set_shortname( "VC-1") |
47 | 58 | set_subcategory( SUBCAT_INPUT_DEMUX ) |
48 | 58 | set_description( N_("VC1 video demuxer" ) ) |
49 | 58 | set_capability( "demux", 0 ) |
50 | 58 | add_float( "vc1-fps", 25.0, FPS_TEXT, FPS_LONGTEXT ) |
51 | 58 | set_callbacks( Open, Close ) |
52 | 58 | add_shortcut( "vc1" ) |
53 | 58 | vlc_module_end () |
54 | | |
55 | | /***************************************************************************** |
56 | | * Local prototypes |
57 | | *****************************************************************************/ |
58 | | typedef struct |
59 | | { |
60 | | vlc_tick_t i_dts; |
61 | | es_out_id_t *p_es; |
62 | | |
63 | | float f_fps; |
64 | | decoder_t *p_packetizer; |
65 | | } demux_sys_t; |
66 | | |
67 | | static int Demux( demux_t * ); |
68 | | static int Control( demux_t *, int, va_list ); |
69 | | |
70 | 0 | #define VC1_PACKET_SIZE 4096 |
71 | | |
72 | | /***************************************************************************** |
73 | | * Open: initializes demux structures |
74 | | *****************************************************************************/ |
75 | | static int Open( vlc_object_t * p_this ) |
76 | | { |
77 | | demux_t *p_demux = (demux_t*)p_this; |
78 | | demux_sys_t *p_sys; |
79 | | const uint8_t *p_peek; |
80 | | es_format_t fmt; |
81 | | |
82 | | if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; |
83 | | |
84 | | if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || |
85 | | p_peek[2] != 0x01 || p_peek[3] != 0x0f ) /* Sequence header */ |
86 | | { |
87 | | if( !p_demux->obj.force ) |
88 | | { |
89 | | msg_Warn( p_demux, "vc-1 module discarded (no startcode)" ); |
90 | | return VLC_EGENERIC; |
91 | | } |
92 | | |
93 | | msg_Err( p_demux, "this doesn't look like a VC-1 ES stream, " |
94 | | "continuing anyway" ); |
95 | | } |
96 | | |
97 | | p_sys = malloc( sizeof( demux_sys_t ) ); |
98 | | if( unlikely(p_sys == NULL) ) |
99 | | return VLC_ENOMEM; |
100 | | |
101 | | p_demux->pf_demux = Demux; |
102 | | p_demux->pf_control= Control; |
103 | | p_demux->p_sys = p_sys; |
104 | | p_sys->p_es = NULL; |
105 | | p_sys->i_dts = 0; |
106 | | p_sys->f_fps = var_CreateGetFloat( p_demux, "vc1-fps" ); |
107 | | if( p_sys->f_fps < 0.001f ) |
108 | | p_sys->f_fps = 0.0f; |
109 | | |
110 | | /* Load the packetizer */ |
111 | | es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_VC1 ); |
112 | | p_sys->p_packetizer = demux_PacketizerNew( VLC_OBJECT(p_demux), &fmt, "VC-1" ); |
113 | | if( !p_sys->p_packetizer ) |
114 | | { |
115 | | free( p_sys ); |
116 | | return VLC_EGENERIC; |
117 | | } |
118 | | return VLC_SUCCESS; |
119 | | } |
120 | | |
121 | | /***************************************************************************** |
122 | | * Close: frees unused data |
123 | | *****************************************************************************/ |
124 | | static void Close( vlc_object_t * p_this ) |
125 | | { |
126 | | demux_t *p_demux = (demux_t*)p_this; |
127 | | demux_sys_t *p_sys = p_demux->p_sys; |
128 | | |
129 | | demux_PacketizerDestroy( p_sys->p_packetizer ); |
130 | | free( p_sys ); |
131 | | } |
132 | | |
133 | | /***************************************************************************** |
134 | | * Demux: reads and demuxes data packets |
135 | | ***************************************************************************** |
136 | | * Returns -1 in case of error, 0 in case of EOF, 1 otherwise |
137 | | *****************************************************************************/ |
138 | | static int Demux( demux_t *p_demux) |
139 | 0 | { |
140 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
141 | 0 | block_t *p_block_in, *p_block_out; |
142 | 0 | bool b_eof = false; |
143 | |
|
144 | 0 | p_block_in = vlc_stream_Block( p_demux->s, VC1_PACKET_SIZE ); |
145 | 0 | if( p_block_in == NULL ) |
146 | 0 | { |
147 | 0 | b_eof = true; |
148 | 0 | } |
149 | 0 | else |
150 | 0 | { |
151 | | /* */ |
152 | 0 | p_block_in->i_dts = p_sys->i_dts != VLC_TICK_INVALID ? p_sys->i_dts : VLC_TICK_0; |
153 | 0 | p_block_in->i_pts = p_block_in->i_dts; |
154 | 0 | } |
155 | |
|
156 | 0 | while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, |
157 | 0 | p_block_in ? &p_block_in : NULL )) ) |
158 | 0 | { |
159 | 0 | while( p_block_out ) |
160 | 0 | { |
161 | 0 | block_t *p_next = p_block_out->p_next; |
162 | |
|
163 | 0 | p_block_out->p_next = NULL; |
164 | |
|
165 | 0 | if( p_sys->p_es == NULL ) |
166 | 0 | { |
167 | 0 | p_sys->p_packetizer->fmt_out.b_packetized = true; |
168 | 0 | p_sys->p_packetizer->fmt_out.i_id = 0; |
169 | 0 | p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out); |
170 | 0 | } |
171 | |
|
172 | 0 | es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_dts ); |
173 | 0 | p_block_out->i_dts = VLC_TICK_0 + p_sys->i_dts; |
174 | 0 | p_block_out->i_pts = VLC_TICK_0 + p_sys->i_dts; |
175 | |
|
176 | 0 | if( likely(p_sys->p_es) ) |
177 | 0 | es_out_Send( p_demux->out, p_sys->p_es, p_block_out ); |
178 | 0 | else |
179 | 0 | { |
180 | 0 | block_Release( p_block_out ); |
181 | 0 | b_eof = true; |
182 | 0 | } |
183 | |
|
184 | 0 | p_block_out = p_next; |
185 | |
|
186 | 0 | if( p_sys->p_packetizer->fmt_out.video.i_frame_rate > 0 && |
187 | 0 | p_sys->p_packetizer->fmt_out.video.i_frame_rate_base > 0 ) |
188 | 0 | p_sys->i_dts += vlc_tick_from_samples( |
189 | 0 | p_sys->p_packetizer->fmt_out.video.i_frame_rate_base, |
190 | 0 | p_sys->p_packetizer->fmt_out.video.i_frame_rate ); |
191 | 0 | else if( p_sys->f_fps > 0.001f ) |
192 | 0 | p_sys->i_dts += (vlc_tick_t)((float) CLOCK_FREQ / p_sys->f_fps); |
193 | 0 | else |
194 | 0 | p_sys->i_dts += VLC_TICK_FROM_MS(40); |
195 | 0 | } |
196 | 0 | } |
197 | |
|
198 | 0 | return b_eof ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS; |
199 | 0 | } |
200 | | |
201 | | /***************************************************************************** |
202 | | * Control: |
203 | | *****************************************************************************/ |
204 | | static int Control( demux_t *p_demux, int i_query, va_list args ) |
205 | 0 | { |
206 | | /* demux_sys_t *p_sys = p_demux->p_sys; */ |
207 | | /* FIXME calculate the bitrate */ |
208 | 0 | if( i_query == DEMUX_SET_TIME ) |
209 | 0 | return VLC_EGENERIC; |
210 | 0 | else |
211 | 0 | return demux_vaControlHelper( p_demux->s, |
212 | 0 | 0, -1, |
213 | 0 | 0, 1, i_query, args ); |
214 | 0 | } |
215 | | |