/src/vlc/modules/demux/rawdv.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * rawdv.c : raw DV input module for vlc |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2007 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Gildas Bazin <gbazin@netcourrier.com> |
7 | | * Paul Corke <paul dot corke at datatote dot co dot uk> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | |
28 | | #ifdef HAVE_CONFIG_H |
29 | | # include "config.h" |
30 | | #endif |
31 | | |
32 | | #include <vlc_common.h> |
33 | | #include <vlc_plugin.h> |
34 | | #include <vlc_demux.h> |
35 | | |
36 | | #include "rawdv.h" |
37 | | |
38 | | /***************************************************************************** |
39 | | * Module descriptor |
40 | | *****************************************************************************/ |
41 | | #define HURRYUP_TEXT N_( "Hurry up" ) |
42 | | #define HURRYUP_LONGTEXT N_( "The demuxer will advance timestamps if the " \ |
43 | | "input can't keep up with the rate." ) |
44 | | |
45 | | static int Open ( vlc_object_t * ); |
46 | | static void Close( vlc_object_t * ); |
47 | | |
48 | 116 | vlc_module_begin () |
49 | 58 | set_shortname( "DV" ) |
50 | 58 | set_description( N_("DV (Digital Video) demuxer") ) |
51 | 58 | set_capability( "demux", 0 ) |
52 | 58 | set_subcategory( SUBCAT_INPUT_DEMUX ) |
53 | 58 | add_bool( "rawdv-hurry-up", false, HURRYUP_TEXT, HURRYUP_LONGTEXT ) |
54 | 58 | set_callbacks( Open, Close ) |
55 | | /* It isn't easy to recognize a raw DV stream. The chances that we'll |
56 | | * mistake a stream from another type for a raw DV stream are too high, so |
57 | | * we'll rely on the file extension to trigger this demux. Alternatively, |
58 | | * it is possible to force this demux. */ |
59 | 58 | add_shortcut( "rawdv" ) |
60 | 58 | add_file_extension("dv") |
61 | 58 | vlc_module_end () |
62 | | |
63 | | |
64 | | /***************************************************************************** |
65 | | A little bit of background information (copied over from libdv glossary). |
66 | | |
67 | | - DIF block: A block of 80 bytes. This is the basic data framing unit of the |
68 | | DVC tape format, analogous to sectors of hard disc. |
69 | | |
70 | | - Video Section: Each DIF sequence contains a video section, consisting of |
71 | | 135 DIF blocks, which are further subdivided into Video Segments. |
72 | | |
73 | | - Video Segment: A video segment consists of 5 DIF blocks, each corresponding |
74 | | to a single compressed macroblock. |
75 | | |
76 | | *****************************************************************************/ |
77 | | |
78 | | /***************************************************************************** |
79 | | * Definitions of structures used by this plugin |
80 | | *****************************************************************************/ |
81 | | typedef struct { |
82 | | int8_t sct; /* Section type (header,subcode,aux,audio,video) */ |
83 | | int8_t dsn; /* DIF sequence number (0-12) */ |
84 | | int fsc; /* First (0)/Second channel (1) */ |
85 | | int8_t dbn; /* DIF block number (0-134) */ |
86 | | } dv_id_t; |
87 | | |
88 | | typedef struct { |
89 | | int dsf; /* DIF sequence flag: 525/60 (0) or 625,50 (1) */ |
90 | | int8_t apt; |
91 | | int tf1; |
92 | | int8_t ap1; |
93 | | int tf2; |
94 | | int8_t ap2; |
95 | | int tf3; |
96 | | int8_t ap3; |
97 | | } dv_header_t; |
98 | | |
99 | | typedef struct |
100 | | { |
101 | | int frame_size; |
102 | | |
103 | | es_out_id_t *p_es_video; |
104 | | es_format_t fmt_video; |
105 | | |
106 | | es_out_id_t *p_es_audio; |
107 | | es_format_t fmt_audio; |
108 | | |
109 | | int i_dsf; |
110 | | double f_rate; |
111 | | int i_bitrate; |
112 | | |
113 | | /* program clock reference (in units of 90kHz) */ |
114 | | vlc_tick_t i_pcr; |
115 | | bool b_hurry_up; |
116 | | } demux_sys_t; |
117 | | |
118 | | /***************************************************************************** |
119 | | * Local prototypes |
120 | | *****************************************************************************/ |
121 | | static int Demux( demux_t * ); |
122 | | static int Control( demux_t *, int i_query, va_list args ); |
123 | | |
124 | | /***************************************************************************** |
125 | | * Open: initializes raw DV demux structures |
126 | | *****************************************************************************/ |
127 | | static int Open( vlc_object_t * p_this ) |
128 | 0 | { |
129 | 0 | demux_t *p_demux = (demux_t*)p_this; |
130 | 0 | demux_sys_t *p_sys; |
131 | |
|
132 | 0 | const uint8_t *p_peek, *p_peek_backup; |
133 | |
|
134 | 0 | uint32_t i_dword; |
135 | 0 | dv_header_t dv_header; |
136 | 0 | dv_id_t dv_id; |
137 | |
|
138 | 0 | if( vlc_stream_Peek( p_demux->s, &p_peek, DV_PAL_FRAME_SIZE ) < |
139 | 0 | DV_NTSC_FRAME_SIZE ) |
140 | 0 | return VLC_EGENERIC; |
141 | | |
142 | 0 | p_peek_backup = p_peek; |
143 | | |
144 | | /* fill in the dv_id_t structure */ |
145 | 0 | i_dword = GetDWBE( p_peek ); p_peek += 4; |
146 | 0 | dv_id.sct = i_dword >> (32 - 3); |
147 | 0 | i_dword <<= 8; |
148 | 0 | dv_id.dsn = i_dword >> (32 - 4); |
149 | 0 | i_dword <<= 4; |
150 | 0 | dv_id.fsc = i_dword >> (32 - 1); |
151 | 0 | i_dword <<= 4; |
152 | 0 | dv_id.dbn = i_dword >> (32 - 8); |
153 | 0 | i_dword <<= 8; |
154 | |
|
155 | 0 | if( dv_id.sct != 0 ) |
156 | 0 | { |
157 | 0 | msg_Warn( p_demux, "not a raw DV stream header" ); |
158 | 0 | return VLC_EGENERIC; |
159 | 0 | } |
160 | | |
161 | | /* fill in the dv_header_t structure */ |
162 | 0 | dv_header.dsf = i_dword >> (32 - 1); |
163 | 0 | i_dword <<= 1; |
164 | 0 | if( i_dword >> (32 - 1) ) /* incorrect bit */ |
165 | 0 | { |
166 | 0 | msg_Warn( p_demux, "incorrect bit" ); |
167 | 0 | return VLC_EGENERIC; |
168 | 0 | } |
169 | | |
170 | 0 | i_dword = GetDWBE( p_peek ); p_peek += 4; |
171 | 0 | i_dword <<= 5; |
172 | 0 | dv_header.apt = i_dword >> (32 - 3); |
173 | 0 | i_dword <<= 3; |
174 | 0 | dv_header.tf1 = i_dword >> (32 - 1); |
175 | 0 | i_dword <<= 5; |
176 | 0 | dv_header.ap1 = i_dword >> (32 - 3); |
177 | 0 | i_dword <<= 3; |
178 | 0 | dv_header.tf2 = i_dword >> (32 - 1); |
179 | 0 | i_dword <<= 5; |
180 | 0 | dv_header.ap2 = i_dword >> (32 - 3); |
181 | 0 | i_dword <<= 3; |
182 | 0 | dv_header.tf3 = i_dword >> (32 - 1); |
183 | 0 | i_dword <<= 5; |
184 | 0 | dv_header.ap3 = i_dword >> (32 - 3); |
185 | |
|
186 | 0 | p_peek += 72; /* skip rest of DIF block */ |
187 | |
|
188 | 0 | p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); |
189 | 0 | if( !p_sys ) |
190 | 0 | return VLC_ENOMEM; |
191 | | |
192 | 0 | p_sys->b_hurry_up = var_CreateGetBool( p_demux, "rawdv-hurry-up" ); |
193 | 0 | msg_Dbg( p_demux, "Realtime DV Source: %s", (p_sys->b_hurry_up)?"Yes":"No" ); |
194 | |
|
195 | 0 | p_sys->i_dsf = dv_header.dsf; |
196 | 0 | p_sys->frame_size = dv_header.dsf ? DV_PAL_FRAME_SIZE |
197 | 0 | : DV_NTSC_FRAME_SIZE; |
198 | 0 | p_sys->f_rate = dv_header.dsf ? 25 : 29.97; |
199 | |
|
200 | 0 | p_sys->i_pcr = 0; |
201 | 0 | p_sys->p_es_video = NULL; |
202 | 0 | p_sys->p_es_audio = NULL; |
203 | |
|
204 | 0 | p_sys->i_bitrate = 0; |
205 | |
|
206 | 0 | es_format_Init( &p_sys->fmt_video, VIDEO_ES, VLC_CODEC_DV ); |
207 | 0 | p_sys->fmt_video.video.i_width = 720; |
208 | 0 | p_sys->fmt_video.video.i_height= dv_header.dsf ? 576 : 480; |
209 | 0 | p_sys->fmt_video.video.i_visible_width = p_sys->fmt_video.video.i_width; |
210 | 0 | p_sys->fmt_video.video.i_visible_height = p_sys->fmt_video.video.i_height; |
211 | |
|
212 | 0 | p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video ); |
213 | | |
214 | | /* Audio stuff */ |
215 | 0 | p_peek = p_peek_backup + 80*6+80*16*3 + 3; /* beginning of AAUX pack */ |
216 | 0 | if( *p_peek == 0x50 ) |
217 | 0 | { |
218 | 0 | dv_get_audio_format( &p_sys->fmt_audio, &p_peek[1] ); |
219 | 0 | p_sys->p_es_audio = es_out_Add( p_demux->out, &p_sys->fmt_audio ); |
220 | 0 | } |
221 | |
|
222 | 0 | p_demux->pf_demux = Demux; |
223 | 0 | p_demux->pf_control = Control; |
224 | 0 | return VLC_SUCCESS; |
225 | 0 | } |
226 | | |
227 | | /***************************************************************************** |
228 | | * Close: frees unused data |
229 | | *****************************************************************************/ |
230 | | static void Close( vlc_object_t *p_this ) |
231 | 0 | { |
232 | 0 | demux_t *p_demux = (demux_t*)p_this; |
233 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
234 | |
|
235 | 0 | var_Destroy( p_demux, "rawdv-hurry-up"); |
236 | 0 | free( p_sys ); |
237 | 0 | } |
238 | | |
239 | | /***************************************************************************** |
240 | | * Demux: reads and demuxes data packets |
241 | | ***************************************************************************** |
242 | | * Returns -1 in case of error, 0 in case of EOF, 1 otherwise |
243 | | *****************************************************************************/ |
244 | | static int Demux( demux_t *p_demux ) |
245 | 0 | { |
246 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
247 | 0 | block_t *p_block; |
248 | |
|
249 | 0 | if( p_sys->b_hurry_up ) |
250 | 0 | { |
251 | | /* 3 frames */ |
252 | 0 | p_sys->i_pcr = vlc_tick_now() + (p_sys->i_dsf ? VLC_TICK_FROM_MS(120) : VLC_TICK_FROM_MS(90)); |
253 | 0 | } |
254 | | |
255 | | /* Call the pace control */ |
256 | 0 | es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_pcr ); |
257 | 0 | p_block = vlc_stream_Block( p_demux->s, p_sys->frame_size ); |
258 | 0 | if( p_block == NULL ) |
259 | 0 | return VLC_DEMUXER_EOF; |
260 | | |
261 | 0 | p_block->i_dts = |
262 | 0 | p_block->i_pts = VLC_TICK_0 + p_sys->i_pcr; |
263 | |
|
264 | 0 | if( likely(p_sys->p_es_audio) ) |
265 | 0 | { |
266 | 0 | bool b_audio = false; |
267 | 0 | es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, |
268 | 0 | p_sys->p_es_audio, &b_audio ); |
269 | 0 | if( b_audio ) |
270 | 0 | { |
271 | 0 | block_t *p_audio_block = dv_extract_audio( p_block ); |
272 | 0 | if( p_audio_block ) |
273 | 0 | es_out_Send( p_demux->out, p_sys->p_es_audio, p_audio_block ); |
274 | 0 | } |
275 | 0 | } |
276 | |
|
277 | 0 | if( likely(p_sys->p_es_video) ) |
278 | 0 | es_out_Send( p_demux->out, p_sys->p_es_video, p_block ); |
279 | 0 | else |
280 | 0 | block_Release( p_block ); |
281 | |
|
282 | 0 | if( !p_sys->b_hurry_up ) |
283 | 0 | { |
284 | 0 | p_sys->i_pcr += vlc_tick_rate_duration( p_sys->f_rate ); |
285 | 0 | } |
286 | |
|
287 | 0 | return VLC_DEMUXER_SUCCESS; |
288 | 0 | } |
289 | | |
290 | | /***************************************************************************** |
291 | | * Control: |
292 | | *****************************************************************************/ |
293 | | static int Control( demux_t *p_demux, int i_query, va_list args ) |
294 | 0 | { |
295 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
296 | | |
297 | | /* XXX: DEMUX_SET_TIME is precise here */ |
298 | 0 | return demux_vaControlHelper( p_demux->s, |
299 | 0 | 0, -1, |
300 | 0 | p_sys->frame_size * p_sys->f_rate * 8, |
301 | 0 | p_sys->frame_size, i_query, args ); |
302 | 0 | } |
303 | | |