From 58baeb4d65aea36efc6b2df941cf9904249cc07e Mon Sep 17 00:00:00 2001 From: MrDave Date: Sat, 4 Mar 2017 12:37:04 -0700 Subject: [PATCH] V4l2 via netcam This commit adds functionality to use a v4l2 device via the netcam_url option. This will allow for more v4l2 devices since the netcam_url uses the ffmpeg libraries which should be able to to decode and transform the unusual pixel formats and sizes. --- configure.ac | 4 ++-- ffmpeg.c | 1 + ffmpeg.h | 1 + motion.1 | 1 + motion_guide.html | 60 ++++++++++++++++++++++++++++++++++++++++------- netcam.c | 13 ++++++---- netcam_rtsp.c | 19 +++++++++++---- 7 files changed, 80 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 24d69045..5ff46718 100644 --- a/configure.ac +++ b/configure.ac @@ -204,13 +204,13 @@ AS_IF([test "x$with_ffmpeg" != "xno"], [ export PKG_CONFIG_PATH ]) - FFMPEG_DEPS="libavutil libavformat libavcodec libswscale" + FFMPEG_DEPS="libavutil libavformat libavcodec libswscale libavdevice" if pkg-config $FFMPEG_DEPS; then FFMPEG_CFLAGS=`pkg-config --cflags $FFMPEG_DEPS` FFMPEG_LIBS=`pkg-config --libs $FFMPEG_DEPS` HAVE_FFMPEG="yes" else - AC_MSG_ERROR([Required ffmpeg packages 'libavutil-dev libavformat-dev libavcodec-dev libswscale-dev' were not found. Please check motion_guide.html and install necessary dependencies or use the '--without-ffmpeg' configuration option.]) + AC_MSG_ERROR([Required ffmpeg packages 'libavutil-dev libavformat-dev libavcodec-dev libswscale-dev libavdevice-dev' were not found. Please check motion_guide.html and install necessary dependencies or use the '--without-ffmpeg' configuration option.]) fi AC_SUBST(FFMPEG_LIBS) AC_SUBST(FFMPEG_CFLAGS) diff --git a/ffmpeg.c b/ffmpeg.c index 3deb180b..8b8ee136 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -767,6 +767,7 @@ void ffmpeg_global_init(void){ av_register_all(); avcodec_register_all(); avformat_network_init(); + avdevice_register_all(); av_log_set_callback((void *)ffmpeg_avcodec_log); ret = av_lockmgr_register(ffmpeg_lockmgr_cb); diff --git a/ffmpeg.h b/ffmpeg.h index efdddeea..ae96b8bc 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -19,6 +19,7 @@ enum TIMELAPSE_TYPE { #include #include #include +#include #if (LIBAVFORMAT_VERSION_MAJOR >= 56) #define MY_PIX_FMT_YUV420P AV_PIX_FMT_YUV420P diff --git a/motion.1 b/motion.1 index 066234a6..0e758597 100644 --- a/motion.1 +++ b/motion.1 @@ -378,6 +378,7 @@ mjpg:// rtsp:// mjpeg:// file:// +v4l2:// .RE The connection string is camera specific. diff --git a/motion_guide.html b/motion_guide.html index 9580e6e4..974b57df 100644 --- a/motion_guide.html +++ b/motion_guide.html @@ -2578,8 +2578,12 @@ The video device to be used for capturing. Default is /dev/video0. See the Basic Setup section of this guide for a additional discussion of this option.

-This is the video4linux device name. Ignore this for net cameras. If a netcam_url is specified, this option will -be ignored. +This option is the preferred way to specify the video4linux device name. If the camera does +not work when specifying the device with this option, it is also possible to specify the device +in the netcam_url with the v4l2 prefix option. The +netcam_url option uses an alternative method to open and operate the +device but has fewer options available. If the netcam_url is used for +either this alternative method or for a normal network camera, the videodevice option is ignored.

v4l2_palette

@@ -2596,6 +2600,12 @@ loop through the available palettes to try to find one that is supported by both Motion will report the supported palettes of the device when Motion starts when the log_level is specified as NTC or higher. The default of 17 is highly preferred since this the native format that Motion uses internally. + +It is possible that after looping through all of the palette options for the camera, Motion will not +find a palette that is acceptable for processing. In this situation, it is possible to use the +netcam_url option with the v4l2 prefix. In the situation that the +netcam_url is used, the v4l2_palette option is ignored. +
  • V4L2_PIX_FMT_SN9C10X : 0 'S910'
  • V4L2_PIX_FMT_SBGGR16 : 1 'BYR2'
  • @@ -2864,19 +2874,53 @@ telling that the signal is lost and when the connection was lost. URL to use if you are using a network camera, size will be autodetected Available prefixes to the URL:
      -
    • http://
    • +
    • http://
    • ftp://
    • mjpg://
    • rtsp://
    • mjpeg://
    • -
    • file:///
    • +
    • file://
    • +
    • v4l2://
    +

    +http:// This prefix uses the traditional http format and opens the netcam looking for a motion jpg image. +

    +ftp:// This prefix opens the ftp site and grabs a static image. The camera will be expected to periodically +replace that static image as it processes images. +

    +mjpg:// This prefix is experimental and when Motion sees this prefix it will replace the mjpg with http and +then process the network camera using the extremely experimental method of grabbing motion jpg images. The +author has not observed that this experimental option is in any way functional. +

    +rtsp:// This prefix is the standard for all modern network cameras. It is recommended that users search the +web or the camera manual for the exact connection string to use for their camera. Once a potential connection +string is found, it should be validated as being functional using a application such as ffplay or vlc. The +connection string that works for these applications is what should be specified for this option. When using +the rtsp format, Motion will ignore the netcam_keepalive and netcam_tolerant_check options. -The prefixes of mjpg and mjpeg are not actual protocols and allow the user to specify -different formats and methods to access the network stream. They are internally translated -into http. For options such as rtsp, it is recommended that the connection string be -validated with other applications such as ffplay or VLC. +

    +mjpeg:// This is another experimental prefix. The mjpeg is replaced with http by Motion internally. The mjpeg +option uses the ffmpeg libraries to retrieve images from the camera and forces the mjpeg format. This option +should be equivalent to using ffplay -f mjpeg http://{yourip}. In certain situations, this option +may result in better results than using the http protocol. Motion will ignore the netcam_keepalive and +netcam_tolerant_check options when this format is specified. +

    +file:// This option allows for the processing of a static image. A process outside of Motion would be needed to +replace the image. A scenario for this would be processing a large number of previously saved images. The file +option would point to a single location such as /home/user/test/currentimage.jpg Then a bash script +running external to Motion would loop through all the images and copy them into currentimage.jpg. +Another situation would be when the ftp server is the same machine as what Motion is running on. In this situation, +rather than logging into the ftp server, this option can be used to point to the actual directory. + +The author believes that while the static image processing option is possible, a preferred approach would be to +encode all the static images to a movie and then use ffmpeg to pipe the movie into a video loopback device. +

    +v4l2:// This option allows for an alternative method of using a v4l2 device that is not natively supported +by Motion. A sample format for the netcam_url would be v4l2:///dev/video0 Internally, this +is equivalent to running the following from the command line ffplay -f v4l2 /dev/video0 +Since this is not the preferred method of specifying a v4l2 device, many of the usual v4l2 controls such as +hue, brightness, palette, etc as well as most of the netcam options are ignored.

    When the netcam_url is defined the video4linux options are ignored.

    diff --git a/netcam.c b/netcam.c index 22bfa466..e6fff775 100644 --- a/netcam.c +++ b/netcam.c @@ -157,6 +157,10 @@ static void netcam_url_parse(struct url_t *parse_url, const char *text_url) re = "(file)://(((.*):(.*))@)?" "([^/:]|[-.a-z0-9]*)(:([0-9]*))?($|(/[^:][/-_.a-z0-9]+))"; + if (!strncmp(text_url, "v4l2", 4)) + re = "(v4l2)://(((.*):(.*))@)?" + "([^/:]|[-.a-z0-9]*)(:([0-9]*))?($|(/[^:][/-_.a-z0-9]+))"; + MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO, "%s: Entry netcam_url_parse data %s", text_url); @@ -2712,14 +2716,15 @@ int netcam_start(struct context *cnt) strcpy(url.service, "http"); /* Put back a real URL service. */ retval = netcam_setup_rtsp(netcam, &url); + } else if ((url.service) && (!strcmp(url.service, "v4l2"))) { + MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, "%s: now calling netcam_setup_v4l2()"); + retval = netcam_setup_rtsp(netcam, &url); } else if ((url.service) && (!strcmp(url.service, "rtsp"))) { - MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, "%s: now calling" - " netcam_setup_rtsp()"); - + MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, "%s: now calling netcam_setup_rtsp()"); retval = netcam_setup_rtsp(netcam, &url); } else { MOTION_LOG(CRT, TYPE_NETCAM, NO_ERRNO, "%s: Invalid netcam service '%s' - " - "must be http, ftp, mjpg, mjpeg or file.", url.service); + "must be http, ftp, mjpg, mjpeg, v4l2 or file.", url.service); netcam_url_free(&url); return -1; } diff --git a/netcam_rtsp.c b/netcam_rtsp.c index 17156869..ccfbcb4e 100644 --- a/netcam_rtsp.c +++ b/netcam_rtsp.c @@ -456,6 +456,7 @@ static int netcam_rtsp_open_context(netcam_context_ptr netcam){ int retcd; char errstr[128]; + char optvalue[9]; if (netcam->rtsp->path == NULL) { if (netcam->rtsp->status == RTSP_NOTCONNECTED){ @@ -476,7 +477,7 @@ static int netcam_rtsp_open_context(netcam_context_ptr netcam){ if (strncmp(netcam->rtsp->path, "http", 4) == 0 ){ netcam->rtsp->format_context->iformat = av_find_input_format("mjpeg"); - } else { + } else if (strncmp(netcam->rtsp->path, "rtsp", 4) == 0 ){ if (netcam->cnt->conf.rtsp_uses_tcp) { av_dict_set(&opts, "rtsp_transport", "tcp", 0); if (netcam->rtsp->status == RTSP_NOTCONNECTED) @@ -487,7 +488,13 @@ static int netcam_rtsp_open_context(netcam_context_ptr netcam){ if (netcam->rtsp->status == RTSP_NOTCONNECTED) MOTION_LOG(NTC, TYPE_NETCAM, NO_ERRNO, "%s: Using udp transport"); } - } + } else { + netcam->rtsp->format_context->iformat = av_find_input_format("v4l2"); + snprintf(optvalue, 4, "%d",netcam->cnt->conf.frame_limit); + av_dict_set(&opts, "framerate", optvalue, 0); + snprintf(optvalue, 9, "%dx%d",netcam->cnt->conf.height,netcam->cnt->conf.width); + av_dict_set(&opts, "video_size", optvalue, 0); + } retcd = avformat_open_input(&netcam->rtsp->format_context, netcam->rtsp->path, NULL, &opts); if (retcd < 0) { @@ -891,15 +898,17 @@ int netcam_setup_rtsp(netcam_context_ptr netcam, struct url_t *url){ * Need a method to query the path and * determine the authentication type */ - if ((netcam->rtsp->user != NULL) && (netcam->rtsp->pass != NULL)) { + if (strcmp(url->service, "v4l2") == 0) { + ptr = mymalloc(strlen(url->path)); + sprintf((char *)ptr, "%s",url->path); + } else if ((netcam->rtsp->user != NULL) && (netcam->rtsp->pass != NULL)) { ptr = mymalloc(strlen(url->service) + strlen(netcam->connect_host) + 5 + strlen(url->path) + 5 + strlen(netcam->rtsp->user) + strlen(netcam->rtsp->pass) + 4 ); sprintf((char *)ptr, "%s://%s:%s@%s:%d%s", url->service,netcam->rtsp->user,netcam->rtsp->pass, netcam->connect_host, netcam->connect_port, url->path); - } - else { + } else { ptr = mymalloc(strlen(url->service) + strlen(netcam->connect_host) + 5 + strlen(url->path) + 5); sprintf((char *)ptr, "%s://%s:%d%s", url->service,