dc1394.c 29.6 KB
Newer Older
1
2
3
/*****************************************************************************
 * dc1394.c: firewire input module
 *****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2006-2009 VideoLAN
5
6
 *
 * Authors: Xant Majere <xant@xant.net>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
7
8
 *          Rob Shortt <rob@tvcentric.com> - libdc1394 V2 API updates
 *          Frederic Benoist <fridorik@gmail.com> - updates from Rob's work
9
10
11
12
 *
 *****************************************************************************
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
13
 * License as published by the Free Software Foundation;
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 * version 2 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

31
32
33
34
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

35
#include <vlc_common.h>
36
#include <vlc_plugin.h>
37
38
#include <vlc_input.h>
#include <vlc_demux.h>
39
#include <vlc_fs.h>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
40
#include <vlc_picture.h>
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#ifdef HAVE_FCNTL_H
#   include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#elif defined( WIN32 ) && !defined( UNDER_CE )
#   include <io.h>
#endif

#include <sys/ioctl.h>
#include <sys/soundcard.h>

#include <libraw1394/raw1394.h>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
55
#include <dc1394/dc1394.h>
56
57
58
59
60
61
62
63
64

#define MAX_IEEE1394_HOSTS 32
#define MAX_CAMERA_NODES 32

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
65
static int OpenAudioDev( demux_t *p_demux );
66
67
static inline void CloseAudioDev( demux_t *p_demux );

68
vlc_module_begin()
69
70
71
72
    set_description( N_("dc1394 input") )
    set_capability( "access_demux", 10 )
    add_shortcut( "dc1394" )
    set_callbacks( Open, Close )
73
vlc_module_end()
74

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
75
struct demux_sys_t
76
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
77
78
79
80
    /* camera info */
    dc1394_t            *p_dccontext;
    uint32_t            num_cameras;
    dc1394camera_t      *camera;
81
    int                 selected_camera;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
82
83
84
85
    uint64_t            selected_uid;
    picture_t           pic;
    uint32_t            dma_buffers;
    dc1394featureset_t  features;
86
    quadlet_t           supported_framerates;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
87
    bool                reset_bus;
88

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
89
90
91
    /* video info */
    char                *video_device;
    dc1394video_mode_t  video_mode;
92
93
94
95
96
97
98
    int                 width;
    int                 height;
    int                 frame_size;
    int                 frame_rate;
    unsigned int        brightness;
    unsigned int        focus;
    es_out_id_t         *p_es_video;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
99
    dc1394video_frame_t *frame;
100
101
102
103
104
105
106
107

    /* audio stuff */
    int                 i_sample_rate;
    int                 channels;
    int                 i_audio_max_frame_size;
    int                 fd_audio;
    char                *audio_device;
    es_out_id_t         *p_es_audio;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
108
};
109
110
111
112
113
114
115
116
117
118
119

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int Demux( demux_t *p_demux );
static int Control( demux_t *, int, va_list );
static block_t *GrabVideo( demux_t *p_demux );
static block_t *GrabAudio( demux_t *p_demux );
static int process_options( demux_t *p_demux);

/*****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
120
 * FindCameras
121
 *****************************************************************************/
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
122
static int FindCamera( demux_sys_t *sys, demux_t *p_demux )
123
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
124
    dc1394camera_list_t *list;
ivoire's avatar
ivoire committed
125
    int i_ret = VLC_EGENERIC;
126
127
128

    msg_Dbg( p_demux, "Scanning for ieee1394 ports ..." );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
129
130
131
    if( dc1394_camera_enumerate (sys->p_dccontext, &list) != DC1394_SUCCESS )
    {
        msg_Err(p_demux, "Can not ennumerate cameras");
ivoire's avatar
ivoire committed
132
        goto end;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
133
    }
134

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
135
136
137
    if( list->num == 0 )
    {
        msg_Err(p_demux, "Can not find cameras");
ivoire's avatar
ivoire committed
138
        goto end;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
139
140
141
142
    }

    sys->num_cameras = list->num;
    msg_Dbg( p_demux, "Found %d dc1394 cameras.", list->num);
143

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
144
145
146
147
148
149
    if( sys->selected_uid )
    {
        int found = 0;
        for( unsigned i = 0; i < sys->num_cameras; i++ )
        {
            if( list->ids[i].guid == sys->selected_uid )
150
            {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
151
152
153
154
                sys->camera = dc1394_camera_new(sys->p_dccontext,
                                                list->ids[i].guid);
                found++;
                break;
155
156
            }
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
157
158
159
160
        if( !found )
        {
            msg_Err( p_demux, "Can't find camera with uid : 0x%llx.",
                     sys->selected_uid );
ivoire's avatar
ivoire committed
161
            goto end;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
162
163
164
165
166
167
        }
    }
    else if( sys->selected_camera >= (int)list->num )
    {
        msg_Err( p_demux, "There are not this many cameras. (%d/%d)",
                 sys->selected_camera, sys->num_cameras );
ivoire's avatar
ivoire committed
168
        goto end;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
169
170
171
172
173
174
175
176
177
178
    }
    else if( sys->selected_camera >= 0 )
    {
        sys->camera = dc1394_camera_new(sys->p_dccontext,
                    list->ids[sys->selected_camera].guid);
    }
    else
    {
        sys->camera = dc1394_camera_new(sys->p_dccontext,
                                          list->ids[0].guid);
179
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
180

ivoire's avatar
ivoire committed
181
182
183
    i_ret = VLC_SUCCESS;

end:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
184
    dc1394_camera_free_list (list);
ivoire's avatar
ivoire committed
185
    return i_ret;
186
187
188
189
190
191
192
}

/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
193
194
195
196
197
198
    demux_t      *p_demux = (demux_t*)p_this;
    demux_sys_t  *p_sys;
    es_format_t   fmt;
    dc1394error_t res;
    int           i_width;
    int           i_height;
199

200
201
202
    if( strncmp(p_demux->psz_access, "dc1394", 6) != 0 )
        return VLC_EGENERIC;

203
204
205
206
207
208
209
    /* Set up p_demux */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->info.i_update = 0;
    p_demux->info.i_title = 0;
    p_demux->info.i_seekpoint = 0;

ivoire's avatar
ivoire committed
210
    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
211
212
    if( !p_sys )
        return VLC_ENOMEM;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
213

214
215
216
    memset( &fmt, 0, sizeof( es_format_t ) );

    /* DEFAULTS */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
217
218
219
220
221
222
223
224
225
226
227
228
    p_sys->video_mode      = DC1394_VIDEO_MODE_640x480_YUV422;
    p_sys->width           = 640;
    p_sys->height          = 480;
    p_sys->frame_rate      = DC1394_FRAMERATE_15;
    p_sys->brightness      = 200;
    p_sys->focus           = 0;
    p_sys->fd_audio        = -1;
    p_sys->p_dccontext     = NULL;
    p_sys->camera          = NULL;
    p_sys->selected_camera = -1;
    p_sys->dma_buffers     = 1;
    p_sys->reset_bus       = 0;
229
230
231
232
233
234
235
236
237
238
239

    /* PROCESS INPUT OPTIONS */
    if( process_options(p_demux) != VLC_SUCCESS )
    {
        msg_Err( p_demux, "Bad MRL, please check the option line "
                          "(MRL was: %s)",
                          p_demux->psz_path );
        free( p_sys );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
240
241
242
243
    p_sys->p_dccontext = dc1394_new();
    if( !p_sys->p_dccontext )
    {
        msg_Err( p_demux, "Failed to initialise libdc1394");
244
        free( p_sys );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
245
246
247
248
        return VLC_EGENERIC;
    }

    if( FindCamera( p_sys, p_demux ) != VLC_SUCCESS )
ivoire's avatar
ivoire committed
249
250
251
    {
        dc1394_free( p_sys->p_dccontext );
        free( p_sys );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
252
        return VLC_EGENERIC;
ivoire's avatar
ivoire committed
253
    }
254

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
255
    if( !p_sys->camera )
256
257
    {
        msg_Err( p_demux, "No camera found !!" );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
258
        dc1394_free( p_sys->p_dccontext );
259
260
261
262
        free( p_sys );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
263
    if( p_sys->reset_bus )
264
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
265
        if( dc1394_reset_bus( p_sys->camera ) != DC1394_SUCCESS )
266
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
267
            msg_Err( p_demux, "Unable to reset IEEE 1394 bus");
268
269
270
            Close( p_this );
            return VLC_EGENERIC;
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
271
        else msg_Dbg( p_demux, "Successfully reset IEEE 1394 bus");
272
273
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
274
    if( dc1394_camera_reset( p_sys->camera ) != DC1394_SUCCESS )
275
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
276
        msg_Err( p_demux, "Unable to reset camera");
277
278
279
280
        Close( p_this );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
281
282
    if( dc1394_camera_print_info( p_sys->camera,
                  stderr ) != DC1394_SUCCESS )
283
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
284
        msg_Err( p_demux, "Unable to print camera info");
285
286
287
288
        Close( p_this );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
289
290
    if( dc1394_feature_get_all( p_sys->camera,
                &p_sys->features ) != DC1394_SUCCESS )
291
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
292
        msg_Err( p_demux, "Unable to get feature set");
293
294
295
        Close( p_this );
        return VLC_EGENERIC;
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
296
297
    // TODO: only print features if verbosity increased
    dc1394_feature_print_all(&p_sys->features, stderr);
298

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
299
300
#if 0 //"Note that you need to execute this function only if you use exotic video1394 device names. /dev/video1394, /dev/video1394/* and /dev/video1394-* are automatically recognized." http://damien.douxchamps.net/ieee1394/libdc1394/v2.x/api/capture/
    if( p_sys->video_device )
301
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
302
303
304
305
306
307
308
        if( dc1394_capture_set_device_filename( p_sys->camera,
                        p_sys->video_device ) != DC1394_SUCCESS )
        {
            msg_Err( p_demux, "Unable to set video device");
            Close( p_this );
            return VLC_EGENERIC;
        }
309
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
310
#endif
311
312
313

    if( p_sys->focus )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
314
315
316
        if( dc1394_feature_set_value( p_sys->camera,
                      DC1394_FEATURE_FOCUS,
                      p_sys->focus ) != DC1394_SUCCESS )
317
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
318
            msg_Err( p_demux, "Unable to set initial focus to %u",
319
320
                     p_sys->focus );
        }
ivoire's avatar
ivoire committed
321
322
        else
            msg_Dbg( p_demux, "Initial focus set to %u", p_sys->focus );
323
324
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
325
326
327
    if( dc1394_feature_set_value( p_sys->camera,
                  DC1394_FEATURE_FOCUS,
                  p_sys->brightness ) != DC1394_SUCCESS )
328
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
329
330
        msg_Err( p_demux, "Unable to set initial brightness to %u",
                 p_sys->brightness );
331
    }
ivoire's avatar
ivoire committed
332
333
    else
        msg_Dbg( p_demux, "Initial brightness set to %u", p_sys->brightness );
334

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
335
336
    if( dc1394_video_set_framerate( p_sys->camera,
                    p_sys->frame_rate ) != DC1394_SUCCESS )
337
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
338
        msg_Err( p_demux, "Unable to set framerate");
339
340
341
342
        Close( p_this );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
343
344
    if( dc1394_video_set_mode( p_sys->camera,
                   p_sys->video_mode ) != DC1394_SUCCESS )
345
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
346
        msg_Err( p_demux, "Unable to set video mode");
347
348
349
350
        Close( p_this );
        return VLC_EGENERIC;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
351
352
    if( dc1394_video_set_iso_speed( p_sys->camera,
                    DC1394_ISO_SPEED_400 ) != DC1394_SUCCESS )
353
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
354
        msg_Err( p_demux, "Unable to set iso speed");
355
356
357
358
359
        Close( p_this );
        return VLC_EGENERIC;
    }

    /* and setup capture */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
360
361
362
363
364
365
    res = dc1394_capture_setup( p_sys->camera,
                    p_sys->dma_buffers,
                DC1394_CAPTURE_FLAGS_DEFAULT);
    if( res != DC1394_SUCCESS )
    {
        if( res == DC1394_NO_BANDWIDTH )
366
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
367
368
            msg_Err( p_demux ,"No bandwidth: try adding the "
             "\"resetbus\" option" );
369
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
370
        else
371
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
372
            msg_Err( p_demux ,"Unable to setup capture" );
373
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
374
375
        Close( p_this );
        return VLC_EGENERIC;
376
377
378
379
380
    }

    /* TODO - UYV444 chroma converter is missing, when it will be available
     * fourcc will become variable (and not just a fixed value for UYVY)
     */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
381
382
    i_width = p_sys->width;
    i_height = p_sys->height;
383

384
    if( picture_Setup( &p_sys->pic, VLC_CODEC_UYVY,
385
                       i_width, i_height, 1, 1 ) )
386
387
388
389
390
    {
        msg_Err( p_demux ,"unknown chroma" );
        Close( p_this );
        return VLC_EGENERIC;
    }
391

392
    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_UYVY );
393
394
395
396

    fmt.video.i_width = i_width;
    fmt.video.i_height = i_height;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
397
    msg_Dbg( p_demux, "Added new video es %4.4s %dx%d",
398
399
400
401
402
403
             (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );

    p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );

    if( p_sys->audio_device )
    {
404
        if( OpenAudioDev( p_demux ) == VLC_SUCCESS )
405
406
        {
            es_format_t fmt;
407
            es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_S16L ); /* FIXME: hmm, ?? */
408
409
410

            fmt.audio.i_channels = p_sys->channels ? p_sys->channels : 1;
            fmt.audio.i_rate = p_sys->i_sample_rate;
411
            fmt.audio.i_bitspersample = 16;
412
413
414
415
416
            fmt.audio.i_blockalign = fmt.audio.i_channels *
                                     fmt.audio.i_bitspersample / 8;
            fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
                            fmt.audio.i_bitspersample;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
417
            msg_Dbg( p_demux, "New audio es %d channels %dHz",
418
419
420
421
422
423
424
            fmt.audio.i_channels, fmt.audio.i_rate );

            p_sys->p_es_audio = es_out_Add( p_demux->out, &fmt );
        }
    }

    /* have the camera start sending us data */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
425
426
    if( dc1394_video_set_transmission( p_sys->camera,
                       DC1394_ON ) != DC1394_SUCCESS )
427
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
428
429
        msg_Err( p_demux, "Unable to start camera iso transmission" );
        dc1394_capture_stop( p_sys->camera );
430
431
432
        Close( p_this );
        return VLC_EGENERIC;
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
433
434
    msg_Dbg( p_demux, "Set iso transmission" );
    // TODO: reread camera
435
436
437
    return VLC_SUCCESS;
}

438
static int OpenAudioDev( demux_t *p_demux )
439
440
441
442
443
444
{
    demux_sys_t *p_sys = p_demux->p_sys;
    char *psz_device = p_sys->audio_device;
    int i_format = AFMT_S16_LE;
    int result;

445
    p_sys->fd_audio = utf8_open( psz_device, O_RDONLY | O_NONBLOCK );
446
447
    if( p_sys->fd_audio  < 0 )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
448
        msg_Err( p_demux, "Cannot open audio device (%s)", psz_device );
449
        return VLC_EGENERIC;
450
451
452
453
454
455
456
457
    }

    if( !p_sys->i_sample_rate )
        p_sys->i_sample_rate = 44100;

    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_SETFMT, &i_format );
    if( (result  < 0) || (i_format != AFMT_S16_LE) )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
458
        msg_Err( p_demux, "Cannot set audio format (16b little endian) "
459
                          "(%d)", i_format );
460
        goto error;
461
462
463
464
465
    }

    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_CHANNELS, &p_sys->channels );
    if( result < 0 )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
466
        msg_Err( p_demux, "Cannot set audio channels count (%d)",
467
                 p_sys->channels );
468
        goto error;
469
470
471
472
473
    }

    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_SPEED, &p_sys->i_sample_rate );
    if( result < 0 )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
474
475
        msg_Err( p_demux, "Cannot set audio sample rate (%d)",
         p_sys->i_sample_rate );
476
        goto error;
477
478
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
479
    msg_Dbg( p_demux, "Opened adev=`%s' %s %dHz",
480
481
482
483
484
             psz_device,
             (p_sys->channels > 1) ? "stereo" : "mono",
             p_sys->i_sample_rate );

    p_sys->i_audio_max_frame_size = 32 * 1024;
485
486
487
488
489
490
491

    return VLC_SUCCESS;

error:
    CloseAudioDev( p_demux );
    p_sys->fd_audio = -1;
    return VLC_EGENERIC;
492
493
494
495
}

static inline void CloseAudioDev( demux_t *p_demux )
{
496
    demux_sys_t *p_sys = p_demux->p_sys;
497

498
499
    if( p_sys->fd_audio >= 0 )
        close( p_sys->fd_audio );
500
501
502
503
504
505
506
507
508
509
510
}

/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = p_demux->p_sys;

    /* Stop data transmission */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
511
512
513
    if( dc1394_video_set_transmission( p_sys->camera,
                       DC1394_OFF ) != DC1394_SUCCESS )
        msg_Err( p_demux, "Unable to stop camera iso transmission" );
514
515

    /* Close camera */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
516
    dc1394_capture_stop( p_sys->camera );
517
518
519

    CloseAudioDev( p_demux );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
520
521
522
    dc1394_camera_free(p_sys->camera);
    dc1394_free(p_sys->p_dccontext);

ivoire's avatar
ivoire committed
523
    free( p_sys->video_device );
524
    free( p_sys->audio_device );
525
526
527
    free( p_sys );
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
528
#if 0
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
static void MovePixelUYVY( void *src, int spos, void *dst, int dpos )
{
    char u,v,y;
    u_char  *sc;
    u_char  *dc;

    sc = (u_char *)src + (spos*2);
    if( spos % 2 )
    {
        v = sc[0];
        y = sc[1];
        u = *(sc -2);
    }
    else
    {
        u = sc[0];
        y = sc[1];
        v = sc[2];
    }
    dc = (u_char *)dst+(dpos*2);
    if( dpos % 2 )
    {
        dc[0] = v;
        dc[1] = y;
    }
    else
    {
        dc[0] = u;
        dc[1] = y;
    }
}
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
560
#endif
561
562
563
564
565
566
567
568
569

/*****************************************************************************
 * Demux:
 *****************************************************************************/
static block_t *GrabVideo( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block = NULL;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
570
571
572
    if( dc1394_capture_dequeue( p_sys->camera,
                DC1394_CAPTURE_POLICY_WAIT,
                &p_sys->frame ) != DC1394_SUCCESS )
573
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
574
575
        msg_Err( p_demux, "Unable to capture a frame" );
        return NULL;
576
577
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
578
579
    p_block = block_New( p_demux, p_sys->frame->size[0] *
                                  p_sys->frame->size[1] * 2 );
580
581
    if( !p_block )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
582
        msg_Err( p_demux, "Can not get block" );
583
584
585
        return NULL;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
586
    if( !p_sys->frame->image )
587
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
588
        msg_Err (p_demux, "Capture buffer empty");
589
590
591
592
        block_Release( p_block );
        return NULL;
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
593
594
    memcpy( p_block->p_buffer, (const char *)p_sys->frame->image,
            p_sys->width * p_sys->height * 2 );
595
596

    p_block->i_pts = p_block->i_dts = mdate();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
597
    dc1394_capture_enqueue( p_sys->camera, p_sys->frame );
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
    return p_block;
}

static block_t *GrabAudio( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    struct audio_buf_info buf_info;
    block_t *p_block = NULL;
    int i_read = 0;
    int i_correct = 0;
    int result = 0;

    p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );
    if( !p_block )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
613
        msg_Warn( p_demux, "Cannot get buffer" );
614
615
616
617
618
619
620
        return NULL;
    }

    i_read = read( p_sys->fd_audio, p_block->p_buffer,
                   p_sys->i_audio_max_frame_size );

    if( i_read <= 0 )
ivoire's avatar
ivoire committed
621
622
    {
        block_Release( p_block );
623
        return NULL;
ivoire's avatar
ivoire committed
624
    }
625
626
627
628
629
630
631
632
633
634

    p_block->i_buffer = i_read;

    /* Correct the date because of kernel buffering */
    i_correct = i_read;
    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info );
    if( result == 0 )
        i_correct += buf_info.bytes;

    p_block->i_pts = p_block->i_dts =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
635
                        mdate() - INT64_C(1000000) * (mtime_t)i_correct /
636
637
638
639
640
641
642
643
644
645
646
                        2 / p_sys->channels / p_sys->i_sample_rate;
    return p_block;
}

static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_blocka = NULL;
    block_t *p_blockv = NULL;

    /* Try grabbing audio frames first */
647
    if( p_sys->fd_audio >= 0 )
648
649
650
        p_blocka = GrabAudio( p_demux );

    /* Try grabbing video frame */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
651
    p_blockv = GrabVideo( p_demux );
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680

    if( !p_blocka && !p_blockv )
    {
        /* Sleep so we do not consume all the cpu, 10ms seems
         * like a good value (100fps)
         */
        msleep( 10000 );
        return 1;
    }

    if( p_blocka )
    {
        es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_blocka->i_pts );
        es_out_Send( p_demux->out, p_sys->p_es_audio, p_blocka );
    }

    if( p_blockv )
    {
        es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_blockv->i_pts );
        es_out_Send( p_demux->out, p_sys->p_es_video, p_blockv );
    }
    return 1;
}

/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
681
    VLC_UNUSED( p_demux );
682
683
684
685
    switch( i_query )
    {
        /* Special for access_demux */
        case DEMUX_CAN_PAUSE:
686
        case DEMUX_CAN_SEEK:
687
688
        case DEMUX_SET_PAUSE_STATE:
        case DEMUX_CAN_CONTROL_PACE:
689
            *va_arg( args, bool * ) = false;
690
691
692
            return VLC_SUCCESS;

        case DEMUX_GET_PTS_DELAY:
693
            *va_arg( args, int64_t * ) = (int64_t)DEFAULT_PTS_DELAY;
694
695
696
            return VLC_SUCCESS;

        case DEMUX_GET_TIME:
697
            *va_arg( args, int64_t * ) = mdate();
698
699
700
701
702
703
704
705
706
707
708
709
            return VLC_SUCCESS;

        /* TODO implement others */
        default:
            return VLC_EGENERIC;
    }
    return VLC_EGENERIC;
}

static int process_options( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
710
    char *psz_dup;
711
712
713
    char *psz_parser;
    char *token = NULL;
    char *state = NULL;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
714
715
    const char *in_size = NULL;
    const char *in_fmt = NULL;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
    float rate_f;

    psz_dup = strdup( p_demux->psz_path );
    psz_parser = psz_dup;
    for( token = strtok_r( psz_parser,":",&state); token;
         token = strtok_r( NULL, ":", &state ) )
    {
        if( strncmp( token, "size=", strlen("size=") ) == 0 )
        {
            token += strlen("size=");
            if( strncmp( token, "160x120", 7 ) == 0 )
            {
                /* TODO - UYV444 chroma converter is needed ...
                    * video size of 160x120 is temporarily disabled
                    */
                msg_Err( p_demux,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
732
733
734
735
                    "video size of 160x120 is actually disabled for lack of"
                    "chroma support. It will relased ASAP, until then try "
                    "an higher size (320x240 and 640x480 are fully supported)" );
                free(psz_dup);
736
737
                return VLC_EGENERIC;
#if 0
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
738
                in_size = "160x120";
739
740
741
742
743
744
                p_sys->width = 160;
                p_sys->height = 120;
#endif
            }
            else if( strncmp( token, "320x240", 7 ) == 0 )
            {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
745
                in_size = "320x240";
746
747
748
749
750
                p_sys->width = 320;
                p_sys->height = 240;
            }
            else if( strncmp( token, "640x480", 7 ) == 0 )
            {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
751
                in_size = "640x480";
752
753
754
755
756
757
758
759
760
761
                p_sys->width = 640;
                p_sys->height = 480;
            }
            else
            {
                msg_Err( p_demux,
                    "This program currently suppots frame sizes of"
                    " 160x120, 320x240, and 640x480. "
                    "Please specify one of them. You have specified %s.",
                    token );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
762
                free(psz_dup);
763
764
765
766
                return VLC_EGENERIC;
            }
            msg_Dbg( p_demux, "Requested video size : %s",token );
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
        if( strncmp( token, "format=", strlen("format=") ) == 0 )
        {
            token += strlen("format=");
            if( strncmp( token, "YUV411", 6 ) == 0 )
            {
                in_fmt = "YUV411";
            }
            else if( strncmp( token, "YUV422", 6 ) == 0 )
            {
                in_fmt = "YUV422";
            }
            else if( strncmp( token, "YUV444", 6 ) == 0 )
            {
                in_fmt = "YUV444";
            }
            else if( strncmp( token, "RGB8", 4 ) == 0 )
            {
                in_fmt = "RGB8";
            }
            else if( strncmp( token, "MONO8", 5 ) == 0 )
            {
                in_fmt = "MONO8";
            }
            else if( strncmp( token, "MONO16", 6 ) == 0 )
            {
                in_fmt = "MONO16";
            }
            else
            {
                msg_Err( p_demux, "Invalid format %s.", token );
                free(psz_dup);
                return VLC_EGENERIC;
            }
            msg_Dbg( p_demux, "Requested video format : %s", token );
        }
802
803
804
805
806
        else if( strncmp( token, "fps=", strlen( "fps=" ) ) == 0 )
        {
            token += strlen("fps=");
            sscanf( token, "%g", &rate_f );
            if( rate_f == 1.875 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
807
                p_sys->frame_rate = DC1394_FRAMERATE_1_875;
808
            else if( rate_f == 3.75 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
809
                p_sys->frame_rate = DC1394_FRAMERATE_3_75;
810
            else if( rate_f == 7.5 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
811
                p_sys->frame_rate = DC1394_FRAMERATE_7_5;
812
            else if( rate_f == 15 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
813
                p_sys->frame_rate = DC1394_FRAMERATE_15;
814
            else if( rate_f == 30 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
815
                p_sys->frame_rate = DC1394_FRAMERATE_30;
816
            else if( rate_f == 60 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
817
                p_sys->frame_rate = DC1394_FRAMERATE_60;
818
819
820
821
822
823
824
            else
            {
                msg_Err( p_demux ,
                    "This program supports framerates of"
                    " 1.875, 3.75, 7.5, 15, 30, 60. "
                    "Please specify one of them. You have specified %s.",
                    token);
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
825
                free(psz_dup);
826
827
828
829
                return VLC_EGENERIC;
            }
            msg_Dbg( p_demux, "Requested frame rate : %s",token );
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
830
831
832
833
834
        else if( strncmp( token, "resetbus", strlen( "resetbus" ) ) == 0 )
        {
            token += strlen("resetbus");
            p_sys->reset_bus = 1;
        }
835
836
837
838
839
840
841
842
843
844
        else if( strncmp( token, "brightness=", strlen( "brightness=" ) ) == 0 )
        {
            int nr = 0;
            token += strlen("brightness=");
            nr = sscanf( token, "%u", &p_sys->brightness);
            if( nr != 1 )
            {
                msg_Err( p_demux, "Bad brightness value '%s', "
                                  "must be an unsigned integer.",
                                  token );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
845
846
847
848
849
850
851
852
853
854
855
856
857
858
                free(psz_dup);
                return VLC_EGENERIC;
            }
        }
        else if( strncmp( token, "buffers=", strlen( "buffers=" ) ) == 0 )
        {
            int nr = 0;
            int in_buf = 0;
            token += strlen("buffers=");
            nr = sscanf( token, "%d", &in_buf);
            if( nr != 1 || in_buf < 1 )
            {
                msg_Err( p_demux, "DMA buffers must be 1 or greater." );
                free(psz_dup);
859
860
                return VLC_EGENERIC;
            }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
861
            else p_sys->dma_buffers = in_buf;
862
863
        }
#if 0
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
864
865
        // NOTE: If controller support is added back, more logic will needed to be added
        //       after the cameras are scanned.
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
        else if( strncmp( token, "controller=", strlen( "controller=" ) ) == 0 )
        {
            int nr = 0;
            token += strlen("controller=");
            nr = sscanf( token, "%u", &p_sys->controller );
            if( nr != 1)
            {
                msg_Err(p_demux, "Bad controller value '%s', "
                                 "must be an unsigned integer.",
                                 token );
                return VLC_EGENERIC;
            }
        }
#endif
        else if( strncmp( token, "camera=", strlen( "camera=" ) ) == 0 )
        {
            int nr = 0;
            token += strlen("camera=");
            nr = sscanf(token,"%u",&p_sys->selected_camera);
            if( nr != 1)
            {
                msg_Err( p_demux, "Bad camera number '%s', "
                                  "must be an unsigned integer.",
                                  token );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
890
                free(psz_dup);
891
892
893
                return VLC_EGENERIC;
            }
        }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
894
        else if( strncmp( token, "vdev=", strlen( "vdev=" ) ) == 0)
895
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
896
897
898
            token += strlen("vdev=");
            p_sys->video_device = strdup(token);
            msg_Dbg( p_demux, "Using video device '%s'.", token );
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
        }
        else if( strncmp( token, "adev=", strlen( "adev=" ) ) == 0 )
        {
            token += strlen("adev=");
            p_sys->audio_device = strdup(token);
            msg_Dbg( p_demux, "Using audio device '%s'.", token );
        }
        else if( strncmp( token, "samplerate=", strlen( "samplerate=" ) ) == 0 )
        {
            token += strlen("samplerate=");
            sscanf( token, "%d", &p_sys->i_sample_rate );
        }
        else if( strncmp( token, "channels=", strlen("channels=" ) ) == 0 )
        {
            token += strlen("channels=");
            sscanf( token, "%d", &p_sys->channels );
        }
        else if( strncmp( token, "focus=", strlen("focus=" ) ) == 0)
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
918
            int nr = 0;
919
            token += strlen("focus=");
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
920
921
922
923
924
925
926
927
928
            nr = sscanf( token, "%u", &p_sys->focus );
            if( nr != 1 )
            {
                msg_Err( p_demux, "Bad focus value '%s', "
                                  "must be an unsigned integer.",
                                  token );
                free(psz_dup);
                return VLC_EGENERIC;
            }
929
930
931
932
        }
        else if( strncmp( token, "uid=", strlen("uid=") ) == 0)
        {
            token += strlen("uid=");
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
933
            sscanf( token, "0x%"SCNx64, &p_sys->selected_uid );
934
935
        }
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971

    // The mode is a combination of size and format and not every format
    // is supported by every size.
    if( in_size)
    {
        if( strcmp( in_size, "160x120") == 0)
        {
            if( in_fmt && (strcmp( in_fmt, "YUV444") != 0) )
                msg_Err(p_demux, "160x120 only supports YUV444 - forcing");
            p_sys->video_mode = DC1394_VIDEO_MODE_160x120_YUV444;
        }
        else if( strcmp( in_size, "320x240") == 0)
        {
            if( in_fmt && (strcmp( in_fmt, "YUV422") != 0) )
                msg_Err(p_demux, "320x240 only supports YUV422 - forcing");
            p_sys->video_mode = DC1394_VIDEO_MODE_320x240_YUV422;
        }
    }
    else
    { // 640x480 default
        if( in_fmt )
        {
            if( strcmp( in_fmt, "RGB8") == 0)
                p_sys->video_mode = DC1394_VIDEO_MODE_640x480_RGB8;
            else if( strcmp( in_fmt, "MONO8") == 0)
                p_sys->video_mode = DC1394_VIDEO_MODE_640x480_MONO8;
            else if( strcmp( in_fmt, "MONO16") == 0)
                p_sys->video_mode = DC1394_VIDEO_MODE_640x480_MONO16;
            else if( strcmp( in_fmt, "YUV411") == 0)
                p_sys->video_mode = DC1394_VIDEO_MODE_640x480_YUV411;
            else // YUV422 default
                p_sys->video_mode = DC1394_VIDEO_MODE_640x480_YUV422;
        }
        else // YUV422 default
            p_sys->video_mode = DC1394_VIDEO_MODE_640x480_YUV422;
    }
ivoire's avatar
ivoire committed
972
973

    free( psz_dup );
974
975
    return VLC_SUCCESS;
}