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;
}