]> git.sesse.net Git - vlc/blobdiff - modules/access/dc1394.c
mmdevice: fix crash if several channel volumes change (fixes #12086)
[vlc] / modules / access / dc1394.c
index e7dcfbb29d04f52f6c485638a9c171250ee1641e..4d12cf330369a7f48dfa16ac8c52d2429de28060 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * dc1394.c: firewire input module
+ * dc1394.c: IIDC (DCAM) FireWire input module
  *****************************************************************************
  * Copyright (C) 2006-2009 VideoLAN
  *
@@ -8,20 +8,20 @@
  *          Frederic Benoist <fridorik@gmail.com> - updates from Rob's work
  *
  *****************************************************************************
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * 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.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
  *
- * 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
+ * This program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
-#include <vlc_input.h>
 #include <vlc_demux.h>
-#include <vlc_charset.h>
-#include <vlc_picture.h>
-
-#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>
 #include <dc1394/dc1394.h>
 
 #define MAX_IEEE1394_HOSTS 32
  *****************************************************************************/
 static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
-static void OpenAudioDev( demux_t *p_demux );
-static inline void CloseAudioDev( demux_t *p_demux );
 
-vlc_module_begin ()
-    set_description( N_("dc1394 input") )
+vlc_module_begin()
+    set_shortname( N_("DC1394") )
+    set_description( N_("IIDC Digital Camera (FireWire) input") )
     set_capability( "access_demux", 10 )
-    add_shortcut( "dc1394" )
     set_callbacks( Open, Close )
-vlc_module_end ()
+vlc_module_end()
 
 struct demux_sys_t
 {
@@ -80,10 +62,8 @@ struct demux_sys_t
     dc1394camera_t      *camera;
     int                 selected_camera;
     uint64_t            selected_uid;
-    picture_t           pic;
     uint32_t            dma_buffers;
     dc1394featureset_t  features;
-    quadlet_t           supported_framerates;
     bool                reset_bus;
 
     /* video info */
@@ -97,17 +77,6 @@ struct demux_sys_t
     unsigned int        focus;
     es_out_id_t         *p_es_video;
     dc1394video_frame_t *frame;
-
-    /* audio stuff */
-    int                 i_sample_rate;
-    int                 channels;
-    int                 i_audio_max_frame_size;
-    int                 fd_audio;
-    char                *audio_device;
-#define NO_ROTATION 0
-#define ROTATION_LEFT 1
-#define ROTATION_RIGHT 2
-    es_out_id_t         *p_es_audio;
 };
 
 /*****************************************************************************
@@ -116,7 +85,6 @@ struct demux_sys_t
 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);
 
 /*****************************************************************************
@@ -125,21 +93,20 @@ static int process_options( demux_t *p_demux);
 static int FindCamera( demux_sys_t *sys, demux_t *p_demux )
 {
     dc1394camera_list_t *list;
+    int i_ret = VLC_EGENERIC;
 
     msg_Dbg( p_demux, "Scanning for ieee1394 ports ..." );
 
     if( dc1394_camera_enumerate (sys->p_dccontext, &list) != DC1394_SUCCESS )
     {
         msg_Err(p_demux, "Can not ennumerate cameras");
-        dc1394_camera_free_list (list);
-        return VLC_EGENERIC;
+        goto end;
     }
 
     if( list->num == 0 )
     {
         msg_Err(p_demux, "Can not find cameras");
-        dc1394_camera_free_list (list);
-        return VLC_EGENERIC;
+        goto end;
     }
 
     sys->num_cameras = list->num;
@@ -160,18 +127,16 @@ static int FindCamera( demux_sys_t *sys, demux_t *p_demux )
         }
         if( !found )
         {
-            msg_Err( p_demux, "Can't find camera with uid : 0x%llx.",
+            msg_Err( p_demux, "Can't find camera with uid : 0x%"PRIx64".",
                      sys->selected_uid );
-            dc1394_camera_free_list (list);
-            return VLC_EGENERIC;
+            goto end;
         }
     }
     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 );
-        dc1394_camera_free_list (list);
-        return VLC_EGENERIC;
+        goto end;
     }
     else if( sys->selected_camera >= 0 )
     {
@@ -184,8 +149,11 @@ static int FindCamera( demux_sys_t *sys, demux_t *p_demux )
                                           list->ids[0].guid);
     }
 
+    i_ret = VLC_SUCCESS;
+
+end:
     dc1394_camera_free_list (list);
-    return VLC_SUCCESS;
+    return i_ret;
 }
 
 /*****************************************************************************
@@ -197,8 +165,6 @@ static int Open( vlc_object_t *p_this )
     demux_sys_t  *p_sys;
     es_format_t   fmt;
     dc1394error_t res;
-    int           i_width;
-    int           i_height;
 
     if( strncmp(p_demux->psz_access, "dc1394", 6) != 0 )
         return VLC_EGENERIC;
@@ -223,7 +189,6 @@ static int Open( vlc_object_t *p_this )
     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;
@@ -235,9 +200,8 @@ static int Open( vlc_object_t *p_this )
     {
         msg_Err( p_demux, "Bad MRL, please check the option line "
                           "(MRL was: %s)",
-                          p_demux->psz_path );
+                          p_demux->psz_location );
         free( p_sys );
-        p_demux->p_sys = NULL;
         return VLC_EGENERIC;
     }
 
@@ -245,8 +209,7 @@ static int Open( vlc_object_t *p_this )
     if( !p_sys->p_dccontext )
     {
         msg_Err( p_demux, "Failed to initialise libdc1394");
-        free(p_demux->p_sys);
-        p_demux->p_sys = NULL;
+        free( p_sys );
         return VLC_EGENERIC;
     }
 
@@ -254,7 +217,6 @@ static int Open( vlc_object_t *p_this )
     {
         dc1394_free( p_sys->p_dccontext );
         free( p_sys );
-        p_demux->p_sys = NULL;
         return VLC_EGENERIC;
     }
 
@@ -263,7 +225,6 @@ static int Open( vlc_object_t *p_this )
         msg_Err( p_demux, "No camera found !!" );
         dc1394_free( p_sys->p_dccontext );
         free( p_sys );
-        p_demux->p_sys = NULL;
         return VLC_EGENERIC;
     }
 
@@ -325,7 +286,8 @@ static int Open( vlc_object_t *p_this )
             msg_Err( p_demux, "Unable to set initial focus to %u",
                      p_sys->focus );
         }
-        msg_Dbg( p_demux, "Initial focus set to %u", p_sys->focus );
+        else
+            msg_Dbg( p_demux, "Initial focus set to %u", p_sys->focus );
     }
 
     if( dc1394_feature_set_value( p_sys->camera,
@@ -335,7 +297,8 @@ static int Open( vlc_object_t *p_this )
         msg_Err( p_demux, "Unable to set initial brightness to %u",
                  p_sys->brightness );
     }
-    msg_Dbg( p_demux, "Initial brightness set to %u", p_sys->brightness );
+    else
+        msg_Dbg( p_demux, "Initial brightness set to %u", p_sys->brightness );
 
     if( dc1394_video_set_framerate( p_sys->camera,
                     p_sys->frame_rate ) != DC1394_SUCCESS )
@@ -383,51 +346,16 @@ static int Open( vlc_object_t *p_this )
     /* TODO - UYV444 chroma converter is missing, when it will be available
      * fourcc will become variable (and not just a fixed value for UYVY)
      */
-    i_width = p_sys->width;
-    i_height = p_sys->height;
-
-    if( picture_Setup( &p_sys->pic, VLC_CODEC_UYVY,
-                       i_width, i_height,
-                       i_width * VOUT_ASPECT_FACTOR / i_height ) )
-    {
-        msg_Err( p_demux ,"unknown chroma" );
-        Close( p_this );
-        return VLC_EGENERIC;
-    }
-
     es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_UYVY );
 
-    fmt.video.i_width = i_width;
-    fmt.video.i_height = i_height;
+    fmt.video.i_width = p_sys->width;
+    fmt.video.i_height = p_sys->height;
 
     msg_Dbg( p_demux, "Added new video es %4.4s %dx%d",
              (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 )
-    {
-        OpenAudioDev( p_demux );
-        if( p_sys->fd_audio >= 0 )
-        {
-            es_format_t fmt;
-            es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_S16L ); /* FIXME: hmm, ?? */
-
-            fmt.audio.i_channels = p_sys->channels ? p_sys->channels : 1;
-            fmt.audio.i_rate = p_sys->i_sample_rate;
-            fmt.audio.i_bitspersample = 16;
-            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;
-
-            msg_Dbg( p_demux, "New audio es %d channels %dHz",
-            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 */
     if( dc1394_video_set_transmission( p_sys->camera,
                        DC1394_ON ) != DC1394_SUCCESS )
@@ -442,67 +370,6 @@ static int Open( vlc_object_t *p_this )
     return VLC_SUCCESS;
 }
 
-static void OpenAudioDev( demux_t *p_demux )
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-    char *psz_device = p_sys->audio_device;
-    int i_format = AFMT_S16_LE;
-    int result;
-
-    p_sys->fd_audio = utf8_open( psz_device, O_RDONLY | O_NONBLOCK );
-    if( p_sys->fd_audio  < 0 )
-    {
-        msg_Err( p_demux, "Cannot open audio device (%s)", psz_device );
-        CloseAudioDev( p_demux );
-    }
-
-    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) )
-    {
-        msg_Err( p_demux, "Cannot set audio format (16b little endian) "
-                          "(%d)", i_format );
-        CloseAudioDev( p_demux );
-    }
-
-    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_CHANNELS, &p_sys->channels );
-    if( result < 0 )
-    {
-        msg_Err( p_demux, "Cannot set audio channels count (%d)",
-                 p_sys->channels );
-        CloseAudioDev( p_demux );
-    }
-
-    result = ioctl( p_sys->fd_audio, SNDCTL_DSP_SPEED, &p_sys->i_sample_rate );
-    if( result < 0 )
-    {
-        msg_Err( p_demux, "Cannot set audio sample rate (%d)",
-         p_sys->i_sample_rate );
-        CloseAudioDev( p_demux );
-    }
-
-    msg_Dbg( p_demux, "Opened adev=`%s' %s %dHz",
-             psz_device,
-             (p_sys->channels > 1) ? "stereo" : "mono",
-             p_sys->i_sample_rate );
-
-    p_sys->i_audio_max_frame_size = 32 * 1024;
-}
-
-static inline void CloseAudioDev( demux_t *p_demux )
-{
-    demux_sys_t *p_sys = NULL;
-
-    if( p_demux )
-    {
-        p_sys = p_demux->p_sys;
-        if( p_sys->fd_audio >= 0 )
-            close( p_sys->fd_audio );
-    }
-}
-
 /*****************************************************************************
  * Close:
  *****************************************************************************/
@@ -519,14 +386,10 @@ static void Close( vlc_object_t *p_this )
     /* Close camera */
     dc1394_capture_stop( p_sys->camera );
 
-    CloseAudioDev( p_demux );
-
     dc1394_camera_free(p_sys->camera);
     dc1394_free(p_sys->p_dccontext);
 
-    if( p_sys->audio_device )
-        free( p_sys->audio_device );
-
+    free( p_sys->video_device );
     free( p_sys );
 }
 
@@ -580,8 +443,7 @@ static block_t *GrabVideo( demux_t *p_demux )
         return NULL;
     }
 
-    p_block = block_New( p_demux, p_sys->frame->size[0] *
-                                  p_sys->frame->size[1] * 2 );
+    p_block = block_Alloc( p_sys->frame->size[0] * p_sys->frame->size[1] * 2 );
     if( !p_block )
     {
         msg_Err( p_demux, "Can not get block" );
@@ -603,56 +465,15 @@ static block_t *GrabVideo( demux_t *p_demux )
     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 )
-    {
-        msg_Warn( p_demux, "Cannot get buffer" );
-        return NULL;
-    }
-
-    i_read = read( p_sys->fd_audio, p_block->p_buffer,
-                   p_sys->i_audio_max_frame_size );
-
-    if( i_read <= 0 )
-        return NULL;
-
-    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 =
-                        mdate() - INT64_C(1000000) * (mtime_t)i_correct /
-                        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 */
-    if( p_sys->fd_audio > 0 )
-        p_blocka = GrabAudio( p_demux );
-
     /* Try grabbing video frame */
     p_blockv = GrabVideo( p_demux );
 
-    if( !p_blocka && !p_blockv )
+    if( !p_blockv )
     {
         /* Sleep so we do not consume all the cpu, 10ms seems
          * like a good value (100fps)
@@ -661,12 +482,6 @@ static int Demux( demux_t *p_demux )
         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 );
@@ -717,10 +532,7 @@ static int process_options( demux_t *p_demux )
     const char *in_fmt = NULL;
     float rate_f;
 
-    if( strncmp(p_demux->psz_access, "dc1394", 6) != 0 )
-        return VLC_EGENERIC;
-
-    psz_dup = strdup( p_demux->psz_path );
+    psz_dup = strdup( p_demux->psz_location );
     psz_parser = psz_dup;
     for( token = strtok_r( psz_parser,":",&state); token;
          token = strtok_r( NULL, ":", &state ) )
@@ -902,22 +714,6 @@ static int process_options( demux_t *p_demux )
             p_sys->video_device = strdup(token);
             msg_Dbg( p_demux, "Using video device '%s'.", token );
         }
-        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)
         {
             int nr = 0;
@@ -935,7 +731,7 @@ static int process_options( demux_t *p_demux )
         else if( strncmp( token, "uid=", strlen("uid=") ) == 0)
         {
             token += strlen("uid=");
-            sscanf( token, "0x%llx", &p_sys->selected_uid );
+            sscanf( token, "0x%"SCNx64, &p_sys->selected_uid );
         }
     }
 
@@ -974,5 +770,7 @@ static int process_options( demux_t *p_demux )
         else // YUV422 default
             p_sys->video_mode = DC1394_VIDEO_MODE_640x480_YUV422;
     }
+
+    free( psz_dup );
     return VLC_SUCCESS;
 }