~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/access/v4l/v4l.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 * v4l.c : Video4Linux input module for vlc
3
 
 *****************************************************************************
4
 
 * Copyright (C) 2002-2004 the VideoLAN team
5
 
 * $Id: 3d7602ef23e6addd0241011d4851351668c5c46d $
6
 
 *
7
 
 * Author: Laurent Aimar <fenrir@via.ecp.fr>
8
 
 *         Paul Forgey <paulf at aphrodite dot com>
9
 
 *         Gildas Bazin <gbazin@videolan.org>
10
 
 *         Benjamin Pracht <bigben at videolan dot org>
11
 
 *
12
 
 * This program is free software; you can redistribute it and/or modify
13
 
 * it under the terms of the GNU General Public License as published by
14
 
 * the Free Software Foundation; either version 2 of the License, or
15
 
 * (at your option) any later version.
16
 
 *
17
 
 * This program is distributed in the hope that it will be useful,
18
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 
 * GNU General Public License for more details.
21
 
 *
22
 
 * You should have received a copy of the GNU General Public License
23
 
 * along with this program; if not, write to the Free Software
24
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25
 
 *****************************************************************************/
26
 
 
27
 
/*****************************************************************************
28
 
 * Preamble
29
 
 *****************************************************************************/
30
 
#include <stdlib.h>
31
 
#include <stdio.h>
32
 
#include <string.h>
33
 
 
34
 
#include <vlc/vlc.h>
35
 
#include <vlc/input.h>
36
 
#include <vlc/vout.h>
37
 
#include <codecs.h>
38
 
 
39
 
#include <sys/types.h>
40
 
#include <sys/stat.h>
41
 
#include <sys/ioctl.h>
42
 
#include <unistd.h>
43
 
#include <sys/mman.h>
44
 
#include <errno.h>
45
 
#include <fcntl.h>
46
 
 
47
 
/* From GStreamer's v4l plugin:
48
 
 * Because of some really cool feature in video4linux1, also known as
49
 
 * 'not including sys/types.h and sys/time.h', we had to include it
50
 
 * ourselves. In all their intelligence, these people decided to fix
51
 
 * this in the next version (video4linux2) in such a cool way that it
52
 
 * breaks all compilations of old stuff...
53
 
 * The real problem is actually that linux/time.h doesn't use proper
54
 
 * macro checks before defining types like struct timeval. The proper
55
 
 * fix here is to either fuck the kernel header (which is what we do
56
 
 * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
57
 
 * upstream, which I'll consider doing later on. If you get compiler
58
 
 * errors here, check your linux/time.h && sys/time.h header setup.
59
 
*/
60
 
#define _LINUX_TIME_H
61
 
 
62
 
#include <linux/videodev.h>
63
 
#include "videodev_mjpeg.h"
64
 
 
65
 
#include <sys/soundcard.h>
66
 
 
67
 
/*****************************************************************************
68
 
 * Module descriptior
69
 
 *****************************************************************************/
70
 
static int  Open ( vlc_object_t * );
71
 
static void Close( vlc_object_t * );
72
 
 
73
 
#define CACHING_TEXT N_("Caching value in ms")
74
 
#define CACHING_LONGTEXT N_( \
75
 
    "Caching value for V4L captures. This " \
76
 
    "value should be set in milliseconds." )
77
 
#define VDEV_TEXT N_("Video device name")
78
 
#define VDEV_LONGTEXT N_( \
79
 
    "Name of the video device to use. " \
80
 
    "If you don't specify anything, no video device will be used.")
81
 
#define ADEV_TEXT N_("Audio device name")
82
 
#define ADEV_LONGTEXT N_( \
83
 
    "Name of the audio device to use. " \
84
 
    "If you don't specify anything, no audio device will be used.")
85
 
#define CHROMA_TEXT N_("Video input chroma format")
86
 
#define CHROMA_LONGTEXT N_( \
87
 
    "Force the Video4Linux video device to use a specific chroma format " \
88
 
    "(eg. I420 (default), RV24, etc.)")
89
 
#define FREQUENCY_TEXT N_( "Frequency" )
90
 
#define FREQUENCY_LONGTEXT N_( \
91
 
    "Frequency to capture (in kHz), if applicable." )
92
 
#define CHANNEL_TEXT N_( "Channel" )
93
 
#define CHANNEL_LONGTEXT N_( \
94
 
    "Channel of the card to use (Usually, 0 = tuner, " \
95
 
    "1 = composite, 2 = svideo)." )
96
 
#define NORM_TEXT N_( "Norm" )
97
 
#define NORM_LONGTEXT N_( \
98
 
    "Norm of the stream (Automatic, SECAM, PAL, or NTSC)." )
99
 
#define AUDIO_TEXT N_( "Audio Channel" )
100
 
#define AUDIO_LONGTEXT N_( \
101
 
    "Audio Channel to use, if there are several audio inputs." )
102
 
#define WIDTH_TEXT N_( "Width" )
103
 
#define WIDTH_LONGTEXT N_( "Width of the stream to capture " \
104
 
    "(-1 for autodetect)." )
105
 
#define HEIGHT_TEXT N_( "Height" )
106
 
#define HEIGHT_LONGTEXT N_( "Height of the stream to capture " \
107
 
    "(-1 for autodetect)." )
108
 
#define BRIGHTNESS_TEXT N_( "Brightness" )
109
 
#define BRIGHTNESS_LONGTEXT N_( \
110
 
    "Brightness of the video input." )
111
 
#define HUE_TEXT N_( "Hue" )
112
 
#define HUE_LONGTEXT N_( \
113
 
    "Hue of the video input." )
114
 
#define COLOUR_TEXT N_( "Color" )
115
 
#define COLOUR_LONGTEXT N_( \
116
 
    "Color of the video input." )
117
 
#define CONTRAST_TEXT N_( "Contrast" )
118
 
#define CONTRAST_LONGTEXT N_( \
119
 
    "Contrast of the video input." )
120
 
#define TUNER_TEXT N_( "Tuner" )
121
 
#define TUNER_LONGTEXT N_( "Tuner to use, if there are several ones." )
122
 
#define SAMPLERATE_TEXT N_( "Samplerate" )
123
 
#define SAMPLERATE_LONGTEXT N_( \
124
 
    "Samplerate of the captured audio stream, in Hz (eg: 11025, 22050, 44100)" )
125
 
#define STEREO_TEXT N_( "Stereo" )
126
 
#define STEREO_LONGTEXT N_( \
127
 
    "Capture the audio stream in stereo." )
128
 
#define MJPEG_TEXT N_( "MJPEG" )
129
 
#define MJPEG_LONGTEXT N_(  \
130
 
    "Set this option if the capture device outputs MJPEG" )
131
 
#define DECIMATION_TEXT N_( "Decimation" )
132
 
#define DECIMATION_LONGTEXT N_( \
133
 
    "Decimation level for MJPEG streams" )
134
 
#define QUALITY_TEXT N_( "Quality" )
135
 
#define QUALITY_LONGTEXT N_( "Quality of the stream." )
136
 
#define FPS_TEXT N_( "Framerate" )
137
 
#define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
138
 
    "(-1 for autodetect)." )
139
 
 
140
 
static int i_norm_list[] =
141
 
    { VIDEO_MODE_AUTO, VIDEO_MODE_SECAM, VIDEO_MODE_PAL, VIDEO_MODE_NTSC };
142
 
static char *psz_norm_list_text[] =
143
 
    { N_("Automatic"), N_("SECAM"), N_("PAL"),  N_("NTSC") };
144
 
 
145
 
vlc_module_begin();
146
 
    set_shortname( _("Video4Linux") );
147
 
    set_description( _("Video4Linux input") );
148
 
    set_category( CAT_INPUT );
149
 
    set_subcategory( SUBCAT_INPUT_ACCESS );
150
 
 
151
 
    add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
152
 
                 CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
153
 
    add_string( "v4l-vdev", "/dev/video", 0, VDEV_TEXT, VDEV_LONGTEXT,
154
 
                VLC_FALSE );
155
 
    add_string( "v4l-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
156
 
                VLC_FALSE );
157
 
    add_string( "v4l-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
158
 
                VLC_TRUE );
159
 
    add_float( "v4l-fps", -1.0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE );
160
 
    add_integer( "v4l-samplerate", 44100, NULL, SAMPLERATE_TEXT,
161
 
                SAMPLERATE_LONGTEXT, VLC_TRUE );
162
 
    add_integer( "v4l-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT,
163
 
                VLC_TRUE );
164
 
    add_integer( "v4l-tuner", -1, NULL, TUNER_TEXT, TUNER_LONGTEXT, VLC_TRUE );
165
 
    add_integer( "v4l-norm", VIDEO_MODE_AUTO, NULL, NORM_TEXT, NORM_LONGTEXT,
166
 
                VLC_FALSE );
167
 
        change_integer_list( i_norm_list, psz_norm_list_text, 0 );
168
 
    add_integer( "v4l-frequency", -1, NULL, FREQUENCY_TEXT, FREQUENCY_LONGTEXT,
169
 
                VLC_FALSE );
170
 
    add_integer( "v4l-audio", -1, NULL, AUDIO_TEXT, AUDIO_LONGTEXT, VLC_TRUE );
171
 
    add_bool( "v4l-stereo", VLC_TRUE, NULL, STEREO_TEXT, STEREO_LONGTEXT,
172
 
            VLC_TRUE );
173
 
    add_integer( "v4l-width", 0, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, VLC_TRUE );
174
 
    add_integer( "v4l-height", 0, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT,
175
 
                VLC_TRUE );
176
 
    add_integer( "v4l-brightness", -1, NULL, BRIGHTNESS_TEXT,
177
 
                BRIGHTNESS_LONGTEXT, VLC_TRUE );
178
 
    add_integer( "v4l-colour", -1, NULL, COLOUR_TEXT, COLOUR_LONGTEXT,
179
 
                VLC_TRUE );
180
 
    add_integer( "v4l-hue", -1, NULL, HUE_TEXT, HUE_LONGTEXT, VLC_TRUE );
181
 
    add_integer( "v4l-contrast", -1, NULL, CONTRAST_TEXT, CONTRAST_LONGTEXT,
182
 
                VLC_TRUE );
183
 
    add_bool( "v4l-mjpeg", VLC_FALSE, NULL, MJPEG_TEXT, MJPEG_LONGTEXT,
184
 
            VLC_TRUE );
185
 
    add_integer( "v4l-decimation", 1, NULL, DECIMATION_TEXT,
186
 
            DECIMATION_LONGTEXT, VLC_TRUE );
187
 
    add_integer( "v4l-quality", 100, NULL, QUALITY_TEXT, QUALITY_LONGTEXT,
188
 
            VLC_TRUE );
189
 
 
190
 
    add_shortcut( "v4l" );
191
 
    set_capability( "access_demux", 10 );
192
 
    set_callbacks( Open, Close );
193
 
vlc_module_end();
194
 
 
195
 
/*****************************************************************************
196
 
 * Access: local prototypes
197
 
 *****************************************************************************/
198
 
static int Demux  ( demux_t * );
199
 
static int Control( demux_t *, int, va_list );
200
 
 
201
 
static void ParseMRL    ( demux_t * );
202
 
static int  OpenVideoDev( demux_t *, char * );
203
 
static int  OpenAudioDev( demux_t *, char * );
204
 
 
205
 
static block_t *GrabAudio( demux_t * );
206
 
static block_t *GrabVideo( demux_t * );
207
 
 
208
 
#define MJPEG_BUFFER_SIZE (256*1024)
209
 
 
210
 
struct quicktime_mjpeg_app1
211
 
{
212
 
    uint32_t    i_reserved;             /* set to 0 */
213
 
    uint32_t    i_tag;                  /* 'mjpg' */
214
 
    uint32_t    i_field_size;           /* offset following EOI */
215
 
    uint32_t    i_padded_field_size;    /* offset following EOI+pad */
216
 
    uint32_t    i_next_field;           /* offset to next field */
217
 
    uint32_t    i_DQT_offset;
218
 
    uint32_t    i_DHT_offset;
219
 
    uint32_t    i_SOF_offset;
220
 
    uint32_t    i_SOS_offset;
221
 
    uint32_t    i_data_offset;          /* following SOS marker data */
222
 
};
223
 
 
224
 
static struct
225
 
{
226
 
    int i_v4l;
227
 
    int i_fourcc;
228
 
 
229
 
} v4lchroma_to_fourcc[] =
230
 
{
231
 
    { VIDEO_PALETTE_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) },
232
 
    { VIDEO_PALETTE_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) },
233
 
    { VIDEO_PALETTE_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) },
234
 
    { VIDEO_PALETTE_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) },
235
 
    { VIDEO_PALETTE_RGB24, VLC_FOURCC( 'R', 'V', '2', '4' ) },
236
 
    { VIDEO_PALETTE_RGB32, VLC_FOURCC( 'R', 'V', '3', '2' ) },
237
 
    { VIDEO_PALETTE_YUV422, VLC_FOURCC( 'I', '4', '2', '2' ) },
238
 
    { VIDEO_PALETTE_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) },
239
 
    { VIDEO_PALETTE_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) },
240
 
    { VIDEO_PALETTE_YUV420, VLC_FOURCC( 'I', '4', '2', 'N' ) },
241
 
    { VIDEO_PALETTE_YUV411, VLC_FOURCC( 'I', '4', '1', 'N' ) },
242
 
    { VIDEO_PALETTE_RAW, VLC_FOURCC( 'G', 'R', 'A', 'W' ) },
243
 
    { VIDEO_PALETTE_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) },
244
 
    { VIDEO_PALETTE_YUV420P, VLC_FOURCC( 'I', '4', '2', '0' ) },
245
 
    { VIDEO_PALETTE_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) },
246
 
    { 0, 0 }
247
 
};
248
 
 
249
 
struct demux_sys_t
250
 
{
251
 
    /* Devices */
252
 
    char *psz_device;         /* Main device from MRL, can be video or audio */
253
 
 
254
 
    char *psz_vdev;
255
 
    int  fd_video;
256
 
 
257
 
    char *psz_adev;
258
 
    int  fd_audio;
259
 
 
260
 
    /* Video properties */
261
 
    picture_t pic;
262
 
 
263
 
    int i_fourcc;
264
 
    int i_channel;
265
 
    int i_audio;
266
 
    int i_norm;
267
 
    int i_tuner;
268
 
    int i_frequency;
269
 
    int i_width;
270
 
    int i_height;
271
 
 
272
 
    int i_brightness;
273
 
    int i_hue;
274
 
    int i_colour;
275
 
    int i_contrast;
276
 
 
277
 
    float f_fps;            /* <= 0.0 mean to grab at full rate */
278
 
    mtime_t i_video_pts;    /* only used when f_fps > 0 */
279
 
 
280
 
    vlc_bool_t b_mjpeg;
281
 
    int i_decimation;
282
 
    int i_quality;
283
 
 
284
 
    struct video_capability vid_cap;
285
 
    struct video_mbuf       vid_mbuf;
286
 
    struct mjpeg_requestbuffers mjpeg_buffers;
287
 
 
288
 
    uint8_t *p_video_mmap;
289
 
    int     i_frame_pos;
290
 
 
291
 
    struct video_mmap   vid_mmap;
292
 
    struct video_picture vid_picture;
293
 
 
294
 
    int          i_video_frame_size;
295
 
    es_out_id_t  *p_es_video;
296
 
 
297
 
    /* Audio properties */
298
 
    vlc_fourcc_t i_acodec_raw;
299
 
    int          i_sample_rate;
300
 
    vlc_bool_t   b_stereo;
301
 
    int          i_audio_max_frame_size;
302
 
    block_t      *p_block_audio;
303
 
    es_out_id_t  *p_es_audio;
304
 
};
305
 
 
306
 
/*****************************************************************************
307
 
 * Open: opens v4l device
308
 
 *****************************************************************************
309
 
 *
310
 
 * url: <video device>::::
311
 
 *
312
 
 *****************************************************************************/
313
 
static int Open( vlc_object_t *p_this )
314
 
{
315
 
    demux_t     *p_demux = (demux_t*)p_this;
316
 
    demux_sys_t *p_sys;
317
 
    vlc_value_t val;
318
 
 
319
 
    /* Only when selected */
320
 
    if( *p_demux->psz_access == '\0' )
321
 
        return VLC_EGENERIC;
322
 
 
323
 
    /* Set up p_demux */
324
 
    p_demux->pf_demux = Demux;
325
 
    p_demux->pf_control = Control;
326
 
    p_demux->info.i_update = 0;
327
 
    p_demux->info.i_title = 0;
328
 
    p_demux->info.i_seekpoint = 0;
329
 
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
330
 
    memset( p_sys, 0, sizeof( demux_sys_t ) );
331
 
 
332
 
    var_Create( p_demux, "v4l-audio", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
333
 
    var_Get( p_demux, "v4l-audio", &val );
334
 
    p_sys->i_audio          = val.i_int;
335
 
 
336
 
    var_Create( p_demux, "v4l-channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
337
 
    var_Get( p_demux, "v4l-channel", &val );
338
 
    p_sys->i_channel        = val.i_int;
339
 
 
340
 
    var_Create( p_demux, "v4l-norm", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
341
 
    var_Get( p_demux, "v4l-norm", &val );
342
 
    p_sys->i_norm           = val.i_int;
343
 
 
344
 
    var_Create( p_demux, "v4l-tuner", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
345
 
    var_Get( p_demux, "v4l-tuner", &val );
346
 
    p_sys->i_tuner          = val.i_int;
347
 
 
348
 
    var_Create( p_demux, "v4l-frequency",
349
 
                                    VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
350
 
    var_Get( p_demux, "v4l-frequency", &val );
351
 
    p_sys->i_frequency      = val.i_int;
352
 
 
353
 
    var_Create( p_demux, "v4l-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
354
 
    var_Get( p_demux, "v4l-fps", &val );
355
 
    p_sys->f_fps            = val.f_float;
356
 
 
357
 
    var_Create( p_demux, "v4l-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
358
 
    var_Get( p_demux, "v4l-width", &val );
359
 
    p_sys->i_width          = val.i_int;
360
 
 
361
 
    var_Create( p_demux, "v4l-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
362
 
    var_Get( p_demux, "v4l-height", &val );
363
 
    p_sys->i_height         = val.i_int;
364
 
 
365
 
    p_sys->i_video_pts      = -1;
366
 
 
367
 
    var_Create( p_demux, "v4l-brightness", VLC_VAR_INTEGER |
368
 
                                                        VLC_VAR_DOINHERIT );
369
 
    var_Get( p_demux, "v4l-brightness", &val );
370
 
    p_sys->i_brightness     = val.i_int;
371
 
 
372
 
    var_Create( p_demux, "v4l-hue", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
373
 
    var_Get( p_demux, "v4l-hue", &val );
374
 
    p_sys->i_hue            = -1;
375
 
 
376
 
    var_Create( p_demux, "v4l-colour", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
377
 
    var_Get( p_demux, "v4l-colour", &val );
378
 
    p_sys->i_colour         = val.i_int;
379
 
 
380
 
    var_Create( p_demux, "v4l-contrast", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
381
 
    var_Get( p_demux, "v4l-contrast", &val );
382
 
    p_sys->i_contrast       = val.i_int;
383
 
 
384
 
    var_Create( p_demux, "v4l-mjpeg", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
385
 
    var_Get( p_demux, "v4l-mjpeg", &val );
386
 
    p_sys->b_mjpeg     = val.b_bool;
387
 
 
388
 
    var_Create( p_demux, "v4l-decimation", VLC_VAR_INTEGER |
389
 
                                                            VLC_VAR_DOINHERIT );
390
 
    var_Get( p_demux, "v4l-decimation", &val );
391
 
    p_sys->i_decimation = val.i_int;
392
 
 
393
 
    var_Create( p_demux, "v4l-quality", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
394
 
    var_Get( p_demux, "v4l-quality", &val );
395
 
    p_sys->i_quality = val.i_int;
396
 
 
397
 
    var_Create( p_demux, "v4l-samplerate",
398
 
                                    VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
399
 
    var_Get( p_demux, "v4l-samplerate", &val );
400
 
    p_sys->i_sample_rate  = val.i_int;
401
 
 
402
 
    var_Create( p_demux, "v4l-stereo", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
403
 
    var_Get( p_demux, "v4l-stereo", &val );
404
 
    p_sys->b_stereo       = val.b_bool;
405
 
 
406
 
    p_sys->psz_device = p_sys->psz_vdev = p_sys->psz_adev = NULL;
407
 
    p_sys->fd_video = -1;
408
 
    p_sys->fd_audio = -1;
409
 
 
410
 
    p_sys->p_es_video = p_sys->p_es_audio = 0;
411
 
    p_sys->p_block_audio = 0;
412
 
 
413
 
    ParseMRL( p_demux );
414
 
 
415
 
    /* Find main device (video or audio) */
416
 
    if( p_sys->psz_device && *p_sys->psz_device )
417
 
    {
418
 
        msg_Dbg( p_demux, "main device=`%s'", p_sys->psz_device );
419
 
 
420
 
        /* Try to open as video device */
421
 
        p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_device );
422
 
 
423
 
        if( p_sys->fd_video < 0 )
424
 
        {
425
 
            /* Try to open as audio device */
426
 
            p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_device );
427
 
            if( p_sys->fd_audio >= 0 )
428
 
            {
429
 
                if( p_sys->psz_adev ) free( p_sys->psz_adev );
430
 
                p_sys->psz_adev = p_sys->psz_device;
431
 
                p_sys->psz_device = NULL;
432
 
            }
433
 
        }
434
 
        else
435
 
        {
436
 
            if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
437
 
            p_sys->psz_vdev = p_sys->psz_device;
438
 
            p_sys->psz_device = NULL;
439
 
        }
440
 
    }
441
 
 
442
 
    /* If no device opened, only continue if the access was forced */
443
 
    if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
444
 
    {
445
 
        if( strcmp( p_demux->psz_access, "v4l" ) )
446
 
        {
447
 
            Close( p_this );
448
 
            return VLC_EGENERIC;
449
 
        }
450
 
    }
451
 
 
452
 
    /* Find video device */
453
 
    if( p_sys->fd_video < 0 )
454
 
    {
455
 
        if( !p_sys->psz_vdev || !*p_sys->psz_vdev )
456
 
        {
457
 
            if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
458
 
            p_sys->psz_vdev = var_CreateGetString( p_demux, "v4l-vdev" );;
459
 
        }
460
 
 
461
 
        if( p_sys->psz_vdev && *p_sys->psz_vdev )
462
 
        {
463
 
            p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_vdev );
464
 
        }
465
 
    }
466
 
 
467
 
    /* Find audio device */
468
 
    if( p_sys->fd_audio < 0 )
469
 
    {
470
 
        if( !p_sys->psz_adev || !*p_sys->psz_adev )
471
 
        {
472
 
            if( p_sys->psz_adev ) free( p_sys->psz_adev );
473
 
            p_sys->psz_adev = var_CreateGetString( p_demux, "v4l-adev" );;
474
 
        }
475
 
 
476
 
        if( p_sys->psz_adev && *p_sys->psz_adev )
477
 
        {
478
 
            p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_adev );
479
 
        }
480
 
    }
481
 
 
482
 
    if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
483
 
    {
484
 
        Close( p_this );
485
 
        return VLC_EGENERIC;
486
 
    }
487
 
 
488
 
    msg_Dbg( p_demux, "v4l grabbing started" );
489
 
 
490
 
    /* Declare elementary streams */
491
 
    if( p_sys->fd_video >= 0 )
492
 
    {
493
 
        es_format_t fmt;
494
 
        es_format_Init( &fmt, VIDEO_ES, p_sys->i_fourcc );
495
 
        fmt.video.i_width  = p_sys->i_width;
496
 
        fmt.video.i_height = p_sys->i_height;
497
 
        fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
498
 
 
499
 
        /* Setup rgb mask for RGB formats */
500
 
        if( p_sys->i_fourcc == VLC_FOURCC('R','V','2','4') )
501
 
        {
502
 
            /* This is in BGR format */
503
 
            fmt.video.i_bmask = 0x00ff0000;
504
 
            fmt.video.i_gmask = 0x0000ff00;
505
 
            fmt.video.i_rmask = 0x000000ff;
506
 
        }
507
 
 
508
 
        msg_Dbg( p_demux, "added new video es %4.4s %dx%d",
509
 
                 (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
510
 
        p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
511
 
    }
512
 
 
513
 
    if( p_sys->fd_audio >= 0 )
514
 
    {
515
 
        es_format_t fmt;
516
 
        es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
517
 
 
518
 
        fmt.audio.i_channels = p_sys->b_stereo ? 2 : 1;
519
 
        fmt.audio.i_rate = p_sys->i_sample_rate;
520
 
        fmt.audio.i_bitspersample = 16; // FIXME ?
521
 
        fmt.audio.i_blockalign = fmt.audio.i_channels *
522
 
            fmt.audio.i_bitspersample / 8;
523
 
        fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
524
 
            fmt.audio.i_bitspersample;
525
 
 
526
 
        msg_Dbg( p_demux, "new audio es %d channels %dHz",
527
 
                 fmt.audio.i_channels, fmt.audio.i_rate );
528
 
 
529
 
        p_sys->p_es_audio = es_out_Add( p_demux->out, &fmt );
530
 
    }
531
 
 
532
 
    /* Update default_pts to a suitable value for access */
533
 
    var_Create( p_demux, "v4l-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
534
 
 
535
 
    return VLC_SUCCESS;
536
 
}
537
 
 
538
 
/*****************************************************************************
539
 
 * Close: close device, free resources
540
 
 *****************************************************************************/
541
 
static void Close( vlc_object_t *p_this )
542
 
{
543
 
    demux_t     *p_demux = (demux_t *)p_this;
544
 
    demux_sys_t *p_sys   = p_demux->p_sys;
545
 
 
546
 
    if( p_sys->psz_device ) free( p_sys->psz_device );
547
 
    if( p_sys->psz_vdev )   free( p_sys->psz_vdev );
548
 
    if( p_sys->psz_adev )   free( p_sys->psz_adev );
549
 
    if( p_sys->fd_video >= 0 ) close( p_sys->fd_video );
550
 
    if( p_sys->fd_audio >= 0 ) close( p_sys->fd_audio );
551
 
    if( p_sys->p_block_audio ) block_Release( p_sys->p_block_audio );
552
 
 
553
 
    if( p_sys->b_mjpeg )
554
 
    {
555
 
        int i_noframe = -1;
556
 
        ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT, &i_noframe );
557
 
    }
558
 
 
559
 
    if( p_sys->p_video_mmap && p_sys->p_video_mmap != MAP_FAILED )
560
 
    {
561
 
        if( p_sys->b_mjpeg )
562
 
            munmap( p_sys->p_video_mmap, p_sys->mjpeg_buffers.size *
563
 
                    p_sys->mjpeg_buffers.count );
564
 
        else
565
 
            munmap( p_sys->p_video_mmap, p_sys->vid_mbuf.size );
566
 
    }
567
 
 
568
 
    free( p_sys );
569
 
}
570
 
 
571
 
/*****************************************************************************
572
 
 * Control:
573
 
 *****************************************************************************/
574
 
static int Control( demux_t *p_demux, int i_query, va_list args )
575
 
{
576
 
    vlc_bool_t *pb;
577
 
    int64_t    *pi64;
578
 
 
579
 
    switch( i_query )
580
 
    {
581
 
        /* Special for access_demux */
582
 
        case DEMUX_CAN_PAUSE:
583
 
        case DEMUX_SET_PAUSE_STATE:
584
 
        case DEMUX_CAN_CONTROL_PACE:
585
 
            pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
586
 
            *pb = VLC_FALSE;
587
 
            return VLC_SUCCESS;
588
 
 
589
 
        case DEMUX_GET_PTS_DELAY:
590
 
            pi64 = (int64_t*)va_arg( args, int64_t * );
591
 
            *pi64 = (int64_t)var_GetInteger( p_demux, "v4l-caching" ) * 1000;
592
 
            return VLC_SUCCESS;
593
 
 
594
 
        case DEMUX_GET_TIME:
595
 
            pi64 = (int64_t*)va_arg( args, int64_t * );
596
 
            *pi64 = mdate();
597
 
            return VLC_SUCCESS;
598
 
 
599
 
        /* TODO implement others */
600
 
        default:
601
 
            return VLC_EGENERIC;
602
 
    }
603
 
 
604
 
    return VLC_EGENERIC;
605
 
}
606
 
 
607
 
/*****************************************************************************
608
 
 * Demux:
609
 
 *****************************************************************************/
610
 
static int Demux( demux_t *p_demux )
611
 
{
612
 
    demux_sys_t *p_sys = p_demux->p_sys;
613
 
    es_out_id_t  *p_es = p_sys->p_es_audio;
614
 
    block_t *p_block = NULL;
615
 
 
616
 
    /* Try grabbing audio frames first */
617
 
    if( p_sys->fd_audio < 0 || !( p_block = GrabAudio( p_demux ) ) )
618
 
    {
619
 
        /* Try grabbing video frame */
620
 
        p_es = p_sys->p_es_video;
621
 
        if( p_sys->fd_video > 0 ) p_block = GrabVideo( p_demux );
622
 
    }
623
 
 
624
 
    if( !p_block )
625
 
    {
626
 
        /* Sleep so we do not consume all the cpu, 10ms seems
627
 
         * like a good value (100fps) */
628
 
        msleep( 10000 );
629
 
        return 1;
630
 
    }
631
 
 
632
 
    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
633
 
    es_out_Send( p_demux->out, p_es, p_block );
634
 
 
635
 
    return 1;
636
 
}
637
 
 
638
 
/*****************************************************************************
639
 
 * ParseMRL: parse the options contained in the MRL
640
 
 *****************************************************************************/
641
 
static void ParseMRL( demux_t *p_demux )
642
 
{
643
 
    demux_sys_t *p_sys = p_demux->p_sys;
644
 
 
645
 
    char *psz_dup = strdup( p_demux->psz_path );
646
 
    char *psz_parser = psz_dup;
647
 
 
648
 
    while( *psz_parser && *psz_parser != ':' )
649
 
    {
650
 
        psz_parser++;
651
 
    }
652
 
 
653
 
    if( *psz_parser == ':' )
654
 
    {
655
 
        /* read options */
656
 
        for( ;; )
657
 
        {
658
 
            *psz_parser++ = '\0';
659
 
            if( !strncmp( psz_parser, "channel=", strlen( "channel=" ) ) )
660
 
            {
661
 
                p_sys->i_channel = strtol( psz_parser + strlen( "channel=" ),
662
 
                                           &psz_parser, 0 );
663
 
            }
664
 
            else if( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
665
 
            {
666
 
                psz_parser += strlen( "norm=" );
667
 
                if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
668
 
                {
669
 
                    p_sys->i_norm = VIDEO_MODE_PAL;
670
 
                    psz_parser += strlen( "pal" );
671
 
                }
672
 
                else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
673
 
                {
674
 
                    p_sys->i_norm = VIDEO_MODE_NTSC;
675
 
                    psz_parser += strlen( "ntsc" );
676
 
                }
677
 
                else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
678
 
                {
679
 
                    p_sys->i_norm = VIDEO_MODE_SECAM;
680
 
                    psz_parser += strlen( "secam" );
681
 
                }
682
 
                else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
683
 
                {
684
 
                    p_sys->i_norm = VIDEO_MODE_AUTO;
685
 
                    psz_parser += strlen( "auto" );
686
 
                }
687
 
                else
688
 
                {
689
 
                    p_sys->i_norm = strtol( psz_parser, &psz_parser, 0 );
690
 
                }
691
 
            }
692
 
            else if( !strncmp( psz_parser, "frequency=",
693
 
                               strlen( "frequency=" ) ) )
694
 
            {
695
 
                p_sys->i_frequency =
696
 
                    strtol( psz_parser + strlen( "frequency=" ),
697
 
                            &psz_parser, 0 );
698
 
                if( p_sys->i_frequency < 30000 )
699
 
                {
700
 
                    msg_Warn( p_demux, "v4l syntax has changed : "
701
 
                              "'frequency' is now channel frequency in kHz");
702
 
                }
703
 
            }
704
 
            else if( !strncmp( psz_parser, "audio=", strlen( "audio=" ) ) )
705
 
            {
706
 
                p_sys->i_audio = strtol( psz_parser + strlen( "audio=" ),
707
 
                                         &psz_parser, 0 );
708
 
            }
709
 
            else if( !strncmp( psz_parser, "size=", strlen( "size=" ) ) )
710
 
            {
711
 
                psz_parser += strlen( "size=" );
712
 
                if( !strncmp( psz_parser, "subqcif", strlen( "subqcif" ) ) )
713
 
                {
714
 
                    p_sys->i_width  = 128;
715
 
                    p_sys->i_height = 96;
716
 
                }
717
 
                else if( !strncmp( psz_parser, "qsif", strlen( "qsif" ) ) )
718
 
                {
719
 
                    p_sys->i_width  = 160;
720
 
                    p_sys->i_height = 120;
721
 
                }
722
 
                else if( !strncmp( psz_parser, "qcif", strlen( "qcif" ) ) )
723
 
                {
724
 
                    p_sys->i_width  = 176;
725
 
                    p_sys->i_height = 144;
726
 
                }
727
 
                else if( !strncmp( psz_parser, "sif", strlen( "sif" ) ) )
728
 
                {
729
 
                    p_sys->i_width  = 320;
730
 
                    p_sys->i_height = 244;
731
 
                }
732
 
                else if( !strncmp( psz_parser, "cif", strlen( "cif" ) ) )
733
 
                {
734
 
                    p_sys->i_width  = 352;
735
 
                    p_sys->i_height = 288;
736
 
                }
737
 
                else if( !strncmp( psz_parser, "vga", strlen( "vga" ) ) )
738
 
                {
739
 
                    p_sys->i_width  = 640;
740
 
                    p_sys->i_height = 480;
741
 
                }
742
 
                else
743
 
                {
744
 
                    /* widthxheight */
745
 
                    p_sys->i_width = strtol( psz_parser, &psz_parser, 0 );
746
 
                    if( *psz_parser == 'x' || *psz_parser == 'X')
747
 
                    {
748
 
                        p_sys->i_height = strtol( psz_parser + 1,
749
 
                                                  &psz_parser, 0 );
750
 
                    }
751
 
                    msg_Dbg( p_demux, "WxH %dx%d", p_sys->i_width,
752
 
                             p_sys->i_height );
753
 
                }
754
 
            }
755
 
            else if( !strncmp( psz_parser, "brightness=", strlen( "brightness=" ) ) )
756
 
            {
757
 
                p_sys->i_brightness = strtol( psz_parser + strlen( "brightness=" ),
758
 
                                              &psz_parser, 0 );
759
 
            }
760
 
            else if( !strncmp( psz_parser, "colour=", strlen( "colour=" ) ) )
761
 
            {
762
 
                p_sys->i_colour = strtol( psz_parser + strlen( "colour=" ),
763
 
                                          &psz_parser, 0 );
764
 
            }
765
 
            else if( !strncmp( psz_parser, "hue=", strlen( "hue=" ) ) )
766
 
            {
767
 
                p_sys->i_hue = strtol( psz_parser + strlen( "hue=" ), 
768
 
                                       &psz_parser, 0 );
769
 
            }
770
 
            else if( !strncmp( psz_parser, "contrast=", strlen( "contrast=" ) ) )
771
 
            {
772
 
                p_sys->i_contrast = strtol( psz_parser + strlen( "contrast=" ),
773
 
                                            &psz_parser, 0 );
774
 
            }
775
 
            else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
776
 
            {
777
 
                p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ),
778
 
                                         &psz_parser, 0 );
779
 
            }
780
 
            else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) ) )
781
 
            {
782
 
                int  i_len;
783
 
 
784
 
                psz_parser += strlen( "adev=" );
785
 
                if( strchr( psz_parser, ':' ) )
786
 
                {
787
 
                    i_len = strchr( psz_parser, ':' ) - psz_parser;
788
 
                }
789
 
                else
790
 
                {
791
 
                    i_len = strlen( psz_parser );
792
 
                }
793
 
 
794
 
                p_sys->psz_adev = strndup( psz_parser, i_len );
795
 
 
796
 
                psz_parser += i_len;
797
 
            }
798
 
            else if( !strncmp( psz_parser, "samplerate=",
799
 
                               strlen( "samplerate=" ) ) )
800
 
            {
801
 
                p_sys->i_sample_rate =
802
 
                    strtol( psz_parser + strlen( "samplerate=" ),
803
 
                            &psz_parser, 0 );
804
 
            }
805
 
            else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) )
806
 
            {
807
 
                psz_parser += strlen( "stereo" );
808
 
 
809
 
                p_sys->b_stereo = VLC_TRUE;
810
 
            }
811
 
            else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
812
 
            {
813
 
                psz_parser += strlen( "mono" );
814
 
 
815
 
                p_sys->b_stereo = VLC_FALSE;
816
 
            }
817
 
            else if( !strncmp( psz_parser, "mjpeg", strlen( "mjpeg" ) ) )
818
 
            {
819
 
                psz_parser += strlen( "mjpeg" );
820
 
 
821
 
                p_sys->b_mjpeg = VLC_TRUE;
822
 
            }
823
 
            else if( !strncmp( psz_parser, "decimation=",
824
 
                        strlen( "decimation=" ) ) )
825
 
            {
826
 
                p_sys->i_decimation =
827
 
                    strtol( psz_parser + strlen( "decimation=" ),
828
 
                            &psz_parser, 0 );
829
 
            }
830
 
            else if( !strncmp( psz_parser, "quality=",
831
 
                        strlen( "quality=" ) ) )
832
 
            {
833
 
                p_sys->i_quality =
834
 
                    strtol( psz_parser + strlen( "quality=" ),
835
 
                            &psz_parser, 0 );
836
 
            }
837
 
            else if( !strncmp( psz_parser, "fps=", strlen( "fps=" ) ) )
838
 
            {
839
 
                p_sys->f_fps = strtof( psz_parser + strlen( "fps=" ),
840
 
                                       &psz_parser );
841
 
            }
842
 
            else
843
 
            {
844
 
                msg_Warn( p_demux, "unknown option" );
845
 
            }
846
 
 
847
 
            while( *psz_parser && *psz_parser != ':' )
848
 
            {
849
 
                psz_parser++;
850
 
            }
851
 
 
852
 
            if( *psz_parser == '\0' )
853
 
            {
854
 
                break;
855
 
            }
856
 
        }
857
 
    }
858
 
 
859
 
    if( *psz_dup )
860
 
    {
861
 
        p_sys->psz_device = strdup( psz_dup );
862
 
    }
863
 
    if( psz_dup ) free( psz_dup );
864
 
}
865
 
 
866
 
/*****************************************************************************
867
 
 * OpenVideoDev:
868
 
 *****************************************************************************/
869
 
static int OpenVideoDev( demux_t *p_demux, char *psz_device )
870
 
{
871
 
    demux_sys_t *p_sys = p_demux->p_sys;
872
 
    int i_fd;
873
 
 
874
 
    struct video_channel vid_channel;
875
 
    struct mjpeg_params mjpeg;
876
 
    int i;
877
 
 
878
 
    if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
879
 
    {
880
 
        msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
881
 
        goto vdev_failed;
882
 
    }
883
 
 
884
 
    if( ioctl( i_fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 )
885
 
    {
886
 
        msg_Err( p_demux, "cannot get capabilities (%s)", strerror( errno ) );
887
 
        goto vdev_failed;
888
 
    }
889
 
 
890
 
    msg_Dbg( p_demux,
891
 
             "V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
892
 
             p_sys->vid_cap.name,
893
 
             p_sys->vid_cap.channels,
894
 
             p_sys->vid_cap.audios,
895
 
             p_sys->vid_cap.minwidth,  p_sys->vid_cap.maxwidth,
896
 
             p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight );
897
 
 
898
 
    if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels )
899
 
    {
900
 
        msg_Dbg( p_demux, "invalid channel, falling back on channel 0" );
901
 
        p_sys->i_channel = 0;
902
 
    }
903
 
    if( p_sys->vid_cap.audios && p_sys->i_audio >= p_sys->vid_cap.audios )
904
 
    {
905
 
        msg_Dbg( p_demux, "invalid audio, falling back with no audio" );
906
 
        p_sys->i_audio = -1;
907
 
    }
908
 
 
909
 
    if( p_sys->i_width < p_sys->vid_cap.minwidth ||
910
 
        p_sys->i_width > p_sys->vid_cap.maxwidth )
911
 
    {
912
 
        msg_Dbg( p_demux, "invalid width %i", p_sys->i_width );
913
 
        p_sys->i_width = 0;
914
 
    }
915
 
    if( p_sys->i_height < p_sys->vid_cap.minheight ||
916
 
        p_sys->i_height > p_sys->vid_cap.maxheight )
917
 
    {
918
 
        msg_Dbg( p_demux, "invalid height %i", p_sys->i_height );
919
 
        p_sys->i_height = 0;
920
 
    }
921
 
 
922
 
    if( !( p_sys->vid_cap.type & VID_TYPE_CAPTURE ) )
923
 
    {
924
 
        msg_Err( p_demux, "cannot grab" );
925
 
        goto vdev_failed;
926
 
    }
927
 
 
928
 
    vid_channel.channel = p_sys->i_channel;
929
 
    if( ioctl( i_fd, VIDIOCGCHAN, &vid_channel ) < 0 )
930
 
    {
931
 
        msg_Err( p_demux, "cannot get channel infos (%s)",
932
 
                          strerror( errno ) );
933
 
        goto vdev_failed;
934
 
    }
935
 
    msg_Dbg( p_demux,
936
 
             "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
937
 
             vid_channel.name, vid_channel.channel, vid_channel.tuners,
938
 
             vid_channel.flags, vid_channel.type, vid_channel.norm );
939
 
 
940
 
    if( p_sys->i_tuner >= vid_channel.tuners )
941
 
    {
942
 
        msg_Dbg( p_demux, "invalid tuner, falling back on tuner 0" );
943
 
        p_sys->i_tuner = 0;
944
 
    }
945
 
 
946
 
    vid_channel.norm = p_sys->i_norm;
947
 
    if( ioctl( i_fd, VIDIOCSCHAN, &vid_channel ) < 0 )
948
 
    {
949
 
        msg_Err( p_demux, "cannot set channel (%s)", strerror( errno ) );
950
 
        goto vdev_failed;
951
 
    }
952
 
 
953
 
    if( vid_channel.flags & VIDEO_VC_TUNER )
954
 
    {
955
 
 
956
 
        /* set tuner */
957
 
#if 0
958
 
        struct video_tuner vid_tuner;
959
 
        if( p_sys->i_tuner >= 0 )
960
 
        {
961
 
            vid_tuner.tuner = p_sys->i_tuner;
962
 
            if( ioctl( i_fd, VIDIOCGTUNER, &vid_tuner ) < 0 )
963
 
            {
964
 
                msg_Err( p_demux, "cannot get tuner (%s)", strerror( errno ) );
965
 
                goto vdev_failed;
966
 
            }
967
 
            msg_Dbg( p_demux, "tuner %s low=%d high=%d, flags=0x%x "
968
 
                     "mode=0x%x signal=0x%x",
969
 
                     vid_tuner.name, vid_tuner.rangelow, vid_tuner.rangehigh,
970
 
                     vid_tuner.flags, vid_tuner.mode, vid_tuner.signal );
971
 
 
972
 
            msg_Dbg( p_demux, "setting tuner %s (%d)",
973
 
                     vid_tuner.name, vid_tuner.tuner );
974
 
 
975
 
            /* FIXME FIXME to be checked FIXME FIXME */
976
 
            //vid_tuner.mode = p_sys->i_norm;
977
 
            if( ioctl( i_fd, VIDIOCSTUNER, &vid_tuner ) < 0 )
978
 
            {
979
 
                msg_Err( p_demux, "cannot set tuner (%s)", strerror( errno ) );
980
 
                goto vdev_failed;
981
 
            }
982
 
        }
983
 
#endif
984
 
 
985
 
        /* Show a warning if frequency is < than 30000.
986
 
         * User is certainly usint old syntax. */
987
 
 
988
 
 
989
 
        /* set frequency */
990
 
        if( p_sys->i_frequency >= 0 )
991
 
        {
992
 
            int driver_frequency = p_sys->i_frequency * 16 /1000;
993
 
            if( ioctl( i_fd, VIDIOCSFREQ, &driver_frequency ) < 0 )
994
 
            {
995
 
                msg_Err( p_demux, "cannot set frequency (%s)",
996
 
                                  strerror( errno ) );
997
 
                goto vdev_failed;
998
 
            }
999
 
            msg_Dbg( p_demux, "frequency %d (%d)", p_sys->i_frequency,
1000
 
                                                   driver_frequency );
1001
 
        }
1002
 
    }
1003
 
 
1004
 
    /* set audio */
1005
 
    if( vid_channel.flags & VIDEO_VC_AUDIO )
1006
 
    {
1007
 
        struct video_audio      vid_audio;
1008
 
 
1009
 
        /* XXX TODO volume, balance, ... */
1010
 
        if( p_sys->i_audio >= 0 )
1011
 
        {
1012
 
            vid_audio.audio = p_sys->i_audio;
1013
 
            if( ioctl( i_fd, VIDIOCGAUDIO, &vid_audio ) < 0 )
1014
 
            {
1015
 
                msg_Err( p_demux, "cannot get audio (%s)", strerror( errno ) );
1016
 
                goto vdev_failed;
1017
 
            }
1018
 
 
1019
 
            /* unmute audio */
1020
 
            vid_audio.flags &= ~VIDEO_AUDIO_MUTE;
1021
 
 
1022
 
            if( ioctl( i_fd, VIDIOCSAUDIO, &vid_audio ) < 0 )
1023
 
            {
1024
 
                msg_Err( p_demux, "cannot set audio (%s)", strerror( errno ) );
1025
 
                goto vdev_failed;
1026
 
            }
1027
 
        }
1028
 
 
1029
 
    }
1030
 
 
1031
 
    /* establish basic params with input and norm before feeling width
1032
 
     * or height */
1033
 
    if( p_sys->b_mjpeg )
1034
 
    {
1035
 
        struct quicktime_mjpeg_app1 *p_app1;
1036
 
        int32_t i_offset;
1037
 
 
1038
 
        if( ioctl( i_fd, MJPIOC_G_PARAMS, &mjpeg ) < 0 )
1039
 
        {
1040
 
            msg_Err( p_demux, "cannot get mjpeg params (%s)",
1041
 
                              strerror( errno ) );
1042
 
            goto vdev_failed;
1043
 
        }
1044
 
        mjpeg.input = p_sys->i_channel;
1045
 
        mjpeg.norm  = p_sys->i_norm;
1046
 
        mjpeg.decimation = p_sys->i_decimation;
1047
 
 
1048
 
        if( p_sys->i_width )
1049
 
            mjpeg.img_width = p_sys->i_width / p_sys->i_decimation;
1050
 
        if( p_sys->i_height )
1051
 
            mjpeg.img_height = p_sys->i_height / p_sys->i_decimation;
1052
 
 
1053
 
        /* establish Quicktime APP1 marker while we are here */
1054
 
        mjpeg.APPn = 1;
1055
 
        mjpeg.APP_len = 40;
1056
 
 
1057
 
        /* aligned */
1058
 
        p_app1 = (struct quicktime_mjpeg_app1 *)mjpeg.APP_data;
1059
 
        p_app1->i_reserved = 0;
1060
 
        p_app1->i_tag = VLC_FOURCC( 'm','j','p','g' );
1061
 
        p_app1->i_field_size = 0;
1062
 
        p_app1->i_padded_field_size = 0;
1063
 
        p_app1->i_next_field = 0;
1064
 
        /* XXX WARNING XXX */
1065
 
        /* these's nothing magic about these values.  We are dangerously
1066
 
         * assuming the encoder card is encoding mjpeg-a and is not throwing
1067
 
         * in marker tags we aren't expecting.  It's bad enough we have to
1068
 
         * search through the jpeg output for every frame we grab just to
1069
 
         * find the first field's end marker, so we take this risk to boost
1070
 
         * performance.
1071
 
         * This is really something the driver could do for us because this
1072
 
         * does conform to standards outside of Apple Quicktime.
1073
 
         */
1074
 
        i_offset = 0x2e;
1075
 
        p_app1->i_DQT_offset = hton32( i_offset );
1076
 
        i_offset = 0xb4;
1077
 
        p_app1->i_DHT_offset = hton32( i_offset );
1078
 
        i_offset = 0x258;
1079
 
        p_app1->i_SOF_offset = hton32( i_offset );
1080
 
        i_offset = 0x26b;
1081
 
        p_app1->i_SOS_offset = hton32( i_offset );
1082
 
        i_offset = 0x279;
1083
 
        p_app1->i_data_offset = hton32( i_offset );
1084
 
 
1085
 
        /* SOF and SOS aren't specified by the mjpeg API because they aren't
1086
 
         * optional.  They will be present in the output. */
1087
 
        mjpeg.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT;
1088
 
 
1089
 
        if( ioctl( i_fd, MJPIOC_S_PARAMS, &mjpeg ) < 0 )
1090
 
        {
1091
 
            msg_Err( p_demux, "cannot set mjpeg params (%s)",
1092
 
                              strerror( errno ) );
1093
 
            goto vdev_failed;
1094
 
        }
1095
 
 
1096
 
        p_sys->i_width = mjpeg.img_width * mjpeg.HorDcm;
1097
 
        p_sys->i_height = mjpeg.img_height * mjpeg.VerDcm *
1098
 
            mjpeg.field_per_buff;
1099
 
    }
1100
 
 
1101
 
    /* fix width/height */
1102
 
    if( !p_sys->b_mjpeg && ( p_sys->i_width == 0 || p_sys->i_height == 0 ) )
1103
 
    {
1104
 
        struct video_window vid_win;
1105
 
 
1106
 
        if( ioctl( i_fd, VIDIOCGWIN, &vid_win ) < 0 )
1107
 
        {
1108
 
            msg_Err( p_demux, "cannot get win (%s)", strerror( errno ) );
1109
 
            goto vdev_failed;
1110
 
        }
1111
 
        p_sys->i_width  = vid_win.width;
1112
 
        p_sys->i_height = vid_win.height;
1113
 
 
1114
 
        if( !p_sys->i_width || !p_sys->i_height )
1115
 
        {
1116
 
            p_sys->i_width = p_sys->vid_cap.maxwidth;
1117
 
            p_sys->i_height = p_sys->vid_cap.maxheight;
1118
 
        }
1119
 
 
1120
 
        if( !p_sys->i_width || !p_sys->i_height )
1121
 
        {
1122
 
            msg_Err( p_demux, "invalid video size (%ix%i)",
1123
 
                     p_sys->i_width, p_sys->i_height );
1124
 
            goto vdev_failed;
1125
 
        }
1126
 
 
1127
 
        msg_Dbg( p_demux, "will use %dx%d", p_sys->i_width, p_sys->i_height );
1128
 
    }
1129
 
 
1130
 
    if( !p_sys->b_mjpeg )
1131
 
    {
1132
 
        /* set hue/color/.. */
1133
 
        if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
1134
 
        {
1135
 
            struct video_picture vid_picture = p_sys->vid_picture;
1136
 
 
1137
 
            if( p_sys->i_brightness >= 0 && p_sys->i_brightness < 65536 )
1138
 
            {
1139
 
                vid_picture.brightness = p_sys->i_brightness;
1140
 
            }
1141
 
            if( p_sys->i_colour >= 0 && p_sys->i_colour < 65536 )
1142
 
            {
1143
 
                vid_picture.colour = p_sys->i_colour;
1144
 
            }
1145
 
            if( p_sys->i_hue >= 0 && p_sys->i_hue < 65536 )
1146
 
            {
1147
 
                vid_picture.hue = p_sys->i_hue;
1148
 
            }
1149
 
            if( p_sys->i_contrast  >= 0 && p_sys->i_contrast < 65536 )
1150
 
            {
1151
 
                vid_picture.contrast = p_sys->i_contrast;
1152
 
            }
1153
 
            if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1154
 
            {
1155
 
                msg_Dbg( p_demux, "v4l device uses brightness: %d",
1156
 
                         vid_picture.brightness );
1157
 
                msg_Dbg( p_demux, "v4l device uses colour: %d",
1158
 
                         vid_picture.colour );
1159
 
                msg_Dbg( p_demux, "v4l device uses hue: %d", vid_picture.hue );
1160
 
                msg_Dbg( p_demux, "v4l device uses contrast: %d",
1161
 
                         vid_picture.contrast );
1162
 
                p_sys->vid_picture = vid_picture;
1163
 
            }
1164
 
        }
1165
 
 
1166
 
        /* Find out video format used by device */
1167
 
        if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
1168
 
        {
1169
 
            struct video_picture vid_picture = p_sys->vid_picture;
1170
 
            char *psz;
1171
 
            int i;
1172
 
 
1173
 
            vid_picture.palette = 0;
1174
 
            p_sys->i_fourcc = 0;
1175
 
 
1176
 
            psz = var_CreateGetString( p_demux, "v4l-chroma" );
1177
 
            if( strlen( psz ) >= 4 )
1178
 
            {
1179
 
                int i_chroma = VLC_FOURCC( psz[0], psz[1], psz[2], psz[3] );
1180
 
 
1181
 
                /* Find out v4l chroma code */
1182
 
                for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
1183
 
                {
1184
 
                    if( v4lchroma_to_fourcc[i].i_fourcc == i_chroma )
1185
 
                    {
1186
 
                        vid_picture.palette = v4lchroma_to_fourcc[i].i_v4l;
1187
 
                        break;
1188
 
                    }
1189
 
                }
1190
 
            }
1191
 
            free( psz );
1192
 
 
1193
 
            if( vid_picture.palette &&
1194
 
                !ioctl( i_fd, VIDIOCSPICT, &vid_picture ) )
1195
 
            {
1196
 
                p_sys->vid_picture = vid_picture;
1197
 
            }
1198
 
            else
1199
 
            {
1200
 
                /* Try to set the format to something easy to encode */
1201
 
                vid_picture.palette = VIDEO_PALETTE_YUV420P;
1202
 
                if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1203
 
                {
1204
 
                    p_sys->vid_picture = vid_picture;
1205
 
                }
1206
 
                else
1207
 
                {
1208
 
                    vid_picture.palette = VIDEO_PALETTE_YUV422P;
1209
 
                    if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1210
 
                    {
1211
 
                        p_sys->vid_picture = vid_picture;
1212
 
                    }
1213
 
                }
1214
 
            }
1215
 
 
1216
 
            /* Find out final format */
1217
 
            for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
1218
 
            {
1219
 
                if( v4lchroma_to_fourcc[i].i_v4l == p_sys->vid_picture.palette)
1220
 
                {
1221
 
                    p_sys->i_fourcc = v4lchroma_to_fourcc[i].i_fourcc;
1222
 
                    break;
1223
 
                }
1224
 
            }
1225
 
        }
1226
 
        else
1227
 
        {
1228
 
            msg_Err( p_demux, "ioctl VIDIOCGPICT failed" );
1229
 
            goto vdev_failed;
1230
 
        }
1231
 
    }
1232
 
 
1233
 
    if( p_sys->b_mjpeg )
1234
 
    {
1235
 
        int i;
1236
 
 
1237
 
        p_sys->mjpeg_buffers.count = 8;
1238
 
        p_sys->mjpeg_buffers.size = MJPEG_BUFFER_SIZE;
1239
 
 
1240
 
        if( ioctl( i_fd, MJPIOC_REQBUFS, &p_sys->mjpeg_buffers ) < 0 )
1241
 
        {
1242
 
            msg_Err( p_demux, "mmap unsupported" );
1243
 
            goto vdev_failed;
1244
 
        }
1245
 
 
1246
 
        p_sys->p_video_mmap = mmap( 0,
1247
 
                p_sys->mjpeg_buffers.size * p_sys->mjpeg_buffers.count,
1248
 
                PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, 0 );
1249
 
        if( p_sys->p_video_mmap == MAP_FAILED )
1250
 
        {
1251
 
            msg_Err( p_demux, "mmap failed" );
1252
 
            goto vdev_failed;
1253
 
        }
1254
 
 
1255
 
        p_sys->i_fourcc  = VLC_FOURCC( 'm','j','p','g' );
1256
 
        p_sys->i_frame_pos = -1;
1257
 
 
1258
 
        /* queue up all the frames */
1259
 
        for( i = 0; i < (int)p_sys->mjpeg_buffers.count; i++ )
1260
 
        {
1261
 
            if( ioctl( i_fd, MJPIOC_QBUF_CAPT, &i ) < 0 )
1262
 
            {
1263
 
                msg_Err( p_demux, "unable to queue frame" );
1264
 
                goto vdev_failed;
1265
 
            }
1266
 
        }
1267
 
    }
1268
 
    else
1269
 
    {
1270
 
        /* Fill in picture_t fields */
1271
 
        vout_InitPicture( VLC_OBJECT(p_demux), &p_sys->pic, p_sys->i_fourcc,
1272
 
                          p_sys->i_width, p_sys->i_height, p_sys->i_width *
1273
 
                          VOUT_ASPECT_FACTOR / p_sys->i_height );
1274
 
        if( !p_sys->pic.i_planes )
1275
 
        {
1276
 
            msg_Err( p_demux, "unsupported chroma" );
1277
 
            goto vdev_failed;
1278
 
        }
1279
 
        p_sys->i_video_frame_size = 0;
1280
 
        for( i = 0; i < p_sys->pic.i_planes; i++ )
1281
 
        {
1282
 
            p_sys->i_video_frame_size += p_sys->pic.p[i].i_visible_lines *
1283
 
              p_sys->pic.p[i].i_visible_pitch;
1284
 
        }
1285
 
 
1286
 
        msg_Dbg( p_demux, "v4l device uses frame size: %i",
1287
 
                 p_sys->i_video_frame_size );
1288
 
        msg_Dbg( p_demux, "v4l device uses chroma: %4.4s",
1289
 
                (char*)&p_sys->i_fourcc );
1290
 
 
1291
 
        /* Allocate mmap buffer */
1292
 
        if( ioctl( i_fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )
1293
 
        {
1294
 
            msg_Err( p_demux, "mmap unsupported" );
1295
 
            goto vdev_failed;
1296
 
        }
1297
 
 
1298
 
        p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,
1299
 
                                    PROT_READ|PROT_WRITE, MAP_SHARED,
1300
 
                                    i_fd, 0 );
1301
 
        if( p_sys->p_video_mmap == MAP_FAILED )
1302
 
        {
1303
 
            /* FIXME -> normal read */
1304
 
            msg_Err( p_demux, "mmap failed" );
1305
 
            goto vdev_failed;
1306
 
        }
1307
 
 
1308
 
        /* init grabbing */
1309
 
        p_sys->vid_mmap.frame  = 0;
1310
 
        p_sys->vid_mmap.width  = p_sys->i_width;
1311
 
        p_sys->vid_mmap.height = p_sys->i_height;
1312
 
        p_sys->vid_mmap.format = p_sys->vid_picture.palette;
1313
 
        if( ioctl( i_fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
1314
 
        {
1315
 
            msg_Warn( p_demux, "%4.4s refused", (char*)&p_sys->i_fourcc );
1316
 
            msg_Err( p_demux, "chroma selection failed" );
1317
 
            goto vdev_failed;
1318
 
        }
1319
 
    }
1320
 
    return i_fd;
1321
 
 
1322
 
vdev_failed:
1323
 
 
1324
 
    if( i_fd >= 0 ) close( i_fd );
1325
 
    return -1;
1326
 
}
1327
 
 
1328
 
/*****************************************************************************
1329
 
 * OpenAudioDev:
1330
 
 *****************************************************************************/
1331
 
static int OpenAudioDev( demux_t *p_demux, char *psz_device )
1332
 
{
1333
 
    demux_sys_t *p_sys = p_demux->p_sys;
1334
 
    int i_fd, i_format;
1335
 
 
1336
 
    if( (i_fd = open( psz_device, O_RDONLY | O_NONBLOCK )) < 0 )
1337
 
    {
1338
 
        msg_Err( p_demux, "cannot open audio device (%s)", strerror( errno ) );
1339
 
        goto adev_fail;
1340
 
    }
1341
 
 
1342
 
    i_format = AFMT_S16_LE;
1343
 
    if( ioctl( i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
1344
 
        || i_format != AFMT_S16_LE )
1345
 
    {
1346
 
        msg_Err( p_demux, "cannot set audio format (16b little endian) "
1347
 
                 "(%s)", strerror( errno ) );
1348
 
        goto adev_fail;
1349
 
    }
1350
 
 
1351
 
    if( ioctl( i_fd, SNDCTL_DSP_STEREO,
1352
 
               &p_sys->b_stereo ) < 0 )
1353
 
    {
1354
 
        msg_Err( p_demux, "cannot set audio channels count (%s)",
1355
 
                 strerror( errno ) );
1356
 
        goto adev_fail;
1357
 
    }
1358
 
 
1359
 
    if( ioctl( i_fd, SNDCTL_DSP_SPEED,
1360
 
               &p_sys->i_sample_rate ) < 0 )
1361
 
    {
1362
 
        msg_Err( p_demux, "cannot set audio sample rate (%s)",
1363
 
                 strerror( errno ) );
1364
 
        goto adev_fail;
1365
 
    }
1366
 
 
1367
 
    msg_Dbg( p_demux, "opened adev=`%s' %s %dHz",
1368
 
             psz_device, p_sys->b_stereo ? "stereo" : "mono",
1369
 
             p_sys->i_sample_rate );
1370
 
 
1371
 
    p_sys->i_audio_max_frame_size = 6 * 1024;
1372
 
 
1373
 
    return i_fd;
1374
 
 
1375
 
 adev_fail:
1376
 
 
1377
 
    if( i_fd >= 0 ) close( i_fd );
1378
 
    return -1;
1379
 
}
1380
 
 
1381
 
/*****************************************************************************
1382
 
 * GrabAudio: grab audio
1383
 
 *****************************************************************************/
1384
 
static block_t *GrabAudio( demux_t *p_demux )
1385
 
{
1386
 
    demux_sys_t *p_sys = p_demux->p_sys;
1387
 
    struct audio_buf_info buf_info;
1388
 
    int i_read, i_correct;
1389
 
    block_t *p_block;
1390
 
 
1391
 
    if( p_sys->p_block_audio ) p_block = p_sys->p_block_audio;
1392
 
    else p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );
1393
 
 
1394
 
    if( !p_block )
1395
 
    {
1396
 
        msg_Warn( p_demux, "cannot get block" );
1397
 
        return 0;
1398
 
    }
1399
 
 
1400
 
    p_sys->p_block_audio = p_block;
1401
 
 
1402
 
    i_read = read( p_sys->fd_audio, p_block->p_buffer,
1403
 
                   p_sys->i_audio_max_frame_size );
1404
 
 
1405
 
    if( i_read <= 0 ) return 0;
1406
 
 
1407
 
    p_block->i_buffer = i_read;
1408
 
    p_sys->p_block_audio = 0;
1409
 
 
1410
 
    /* Correct the date because of kernel buffering */
1411
 
    i_correct = i_read;
1412
 
    if( ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )
1413
 
    {
1414
 
        i_correct += buf_info.bytes;
1415
 
    }
1416
 
 
1417
 
    p_block->i_pts = p_block->i_dts =
1418
 
        mdate() - I64C(1000000) * (mtime_t)i_correct /
1419
 
        2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;
1420
 
 
1421
 
    return p_block;
1422
 
}
1423
 
 
1424
 
/*****************************************************************************
1425
 
 * GrabVideo:
1426
 
 *****************************************************************************/
1427
 
static uint8_t *GrabCapture( demux_t *p_demux )
1428
 
{
1429
 
    demux_sys_t *p_sys = p_demux->p_sys;
1430
 
    int i_captured_frame = p_sys->i_frame_pos;
1431
 
 
1432
 
    p_sys->vid_mmap.frame = (p_sys->i_frame_pos + 1) % p_sys->vid_mbuf.frames;
1433
 
 
1434
 
    while( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
1435
 
    {
1436
 
        if( errno != EAGAIN )
1437
 
        {
1438
 
            msg_Err( p_demux, "failed capturing new frame" );
1439
 
            return NULL;
1440
 
        }
1441
 
 
1442
 
        if( p_demux->b_die )
1443
 
        {
1444
 
            return NULL;
1445
 
        }
1446
 
 
1447
 
        msg_Dbg( p_demux, "grab failed, trying again" );
1448
 
    }
1449
 
 
1450
 
    while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 )
1451
 
    {
1452
 
        if( errno != EAGAIN && errno != EINTR )    
1453
 
        {
1454
 
            msg_Err( p_demux, "failed syncing new frame" );
1455
 
            return NULL;
1456
 
        }
1457
 
    }
1458
 
 
1459
 
    p_sys->i_frame_pos = p_sys->vid_mmap.frame;
1460
 
    /* leave i_video_frame_size alone */
1461
 
    return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[i_captured_frame];
1462
 
}
1463
 
 
1464
 
static uint8_t *GrabMJPEG( demux_t *p_demux )
1465
 
{
1466
 
    demux_sys_t *p_sys = p_demux->p_sys;
1467
 
    struct mjpeg_sync sync;
1468
 
    uint8_t *p_frame, *p_field, *p;
1469
 
    uint16_t tag;
1470
 
    uint32_t i_size;
1471
 
    struct quicktime_mjpeg_app1 *p_app1 = NULL;
1472
 
 
1473
 
    /* re-queue the last frame we sync'd */
1474
 
    if( p_sys->i_frame_pos != -1 )
1475
 
    {
1476
 
        while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT,
1477
 
                                       &p_sys->i_frame_pos ) < 0 )
1478
 
        {
1479
 
            if( errno != EAGAIN && errno != EINTR )
1480
 
            {
1481
 
                msg_Err( p_demux, "failed capturing new frame" );
1482
 
                return NULL;
1483
 
            }
1484
 
        }
1485
 
    }
1486
 
 
1487
 
    /* sync on the next frame */
1488
 
    while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 )
1489
 
    {
1490
 
        if( errno != EAGAIN && errno != EINTR )    
1491
 
        {
1492
 
            msg_Err( p_demux, "failed syncing new frame" );
1493
 
            return NULL;
1494
 
        }
1495
 
    }
1496
 
 
1497
 
    p_sys->i_frame_pos = sync.frame;
1498
 
    p_frame = p_sys->p_video_mmap + p_sys->mjpeg_buffers.size * sync.frame;
1499
 
 
1500
 
    /* p_frame now points to the data.  fix up the Quicktime APP1 marker */
1501
 
    tag = 0xffd9;
1502
 
    tag = hton16( tag );
1503
 
    p_field = p_frame;
1504
 
 
1505
 
    /* look for EOI */
1506
 
    p = memmem( p_field, sync.length, &tag, 2 );
1507
 
 
1508
 
    if( p )
1509
 
    {
1510
 
        p += 2; /* data immediately following EOI */
1511
 
        /* UNALIGNED! */
1512
 
        p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
1513
 
 
1514
 
        i_size = ((uint32_t)(p - p_field));
1515
 
        i_size = hton32( i_size );
1516
 
        memcpy( &p_app1->i_field_size, &i_size, 4 );
1517
 
 
1518
 
        while( *p == 0xff && *(p+1) == 0xff )
1519
 
            p++;
1520
 
 
1521
 
        i_size = ((uint32_t)(p - p_field));
1522
 
        i_size = hton32( i_size );
1523
 
        memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
1524
 
    }
1525
 
 
1526
 
    tag = 0xffd8;
1527
 
    tag = hton16( tag );
1528
 
    p_field = memmem( p, sync.length - (size_t)(p - p_frame), &tag, 2 );
1529
 
 
1530
 
    if( p_field )
1531
 
    {
1532
 
        i_size = (uint32_t)(p_field - p_frame);
1533
 
        i_size = hton32( i_size );
1534
 
        memcpy( &p_app1->i_next_field, &i_size, 4 );
1535
 
 
1536
 
        /* UNALIGNED! */
1537
 
        p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
1538
 
        tag = 0xffd9;
1539
 
        tag = hton16( tag );
1540
 
        p = memmem( p_field, sync.length - (size_t)(p_field - p_frame),
1541
 
                &tag, 2 );
1542
 
 
1543
 
        if( !p )
1544
 
        {
1545
 
            /* sometimes the second field doesn't have the EOI.  just put it
1546
 
             * there
1547
 
             */
1548
 
            p = p_frame + sync.length;
1549
 
            memcpy( p, &tag, 2 );
1550
 
            sync.length += 2;
1551
 
        }
1552
 
 
1553
 
        p += 2;
1554
 
        i_size = (uint32_t)(p - p_field);
1555
 
        i_size = hton32( i_size );
1556
 
        memcpy( &p_app1->i_field_size, &i_size, 4 );
1557
 
        i_size = (uint32_t)(sync.length - (uint32_t)(p_field - p_frame));
1558
 
        i_size = hton32( i_size );
1559
 
        memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
1560
 
    }
1561
 
 
1562
 
    p_sys->i_video_frame_size = sync.length;
1563
 
    return p_frame;
1564
 
}
1565
 
 
1566
 
static block_t *GrabVideo( demux_t *p_demux )
1567
 
{
1568
 
    demux_sys_t *p_sys = p_demux->p_sys;
1569
 
    uint8_t     *p_frame;
1570
 
    block_t     *p_block;
1571
 
 
1572
 
    if( p_sys->f_fps >= 0.1 && p_sys->i_video_pts > 0 )
1573
 
    {
1574
 
        mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);
1575
 
 
1576
 
        /* Did we wait long enough ? (frame rate reduction) */
1577
 
        if( p_sys->i_video_pts + i_dur > mdate() ) return 0;
1578
 
    }
1579
 
 
1580
 
    if( p_sys->b_mjpeg ) p_frame = GrabMJPEG( p_demux );
1581
 
    else p_frame = GrabCapture( p_demux );
1582
 
 
1583
 
    if( !p_frame ) return 0;
1584
 
 
1585
 
    if( !( p_block = block_New( p_demux, p_sys->i_video_frame_size ) ) )
1586
 
    {
1587
 
        msg_Warn( p_demux, "cannot get block" );
1588
 
        return 0;
1589
 
    }
1590
 
 
1591
 
    memcpy( p_block->p_buffer, p_frame, p_sys->i_video_frame_size );
1592
 
    p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();
1593
 
 
1594
 
    return p_block;
1595
 
}