Merge pull request #311 from jayslovak/master

Add webp image compression support.  Closes #310  Thanks @jayslovak.
This commit is contained in:
Mr-Dave
2017-02-09 18:47:24 -07:00
committed by GitHub
18 changed files with 177 additions and 37 deletions

View File

@@ -20,6 +20,7 @@ matrix:
- libjpeg8-dev
- libv4l-dev
- libzip-dev
- libwebp-dev
- os: linux
language: c
compiler: gcc
@@ -39,4 +40,5 @@ matrix:
- libjpeg8-dev
- libv4l-dev
- libzip-dev
- libwebp-dev

View File

@@ -15,6 +15,7 @@ Build Packages:
libjpeg8-dev
build-essential
libzip-dev
libwebp-dev
The option to include FFMPEG or Libav functionality in motion is a choice of one OR the other not both.
The packages and library names change frequently and vary across base operating systems. If ffmpeg or
@@ -43,4 +44,4 @@ Once required packages are installed, execute:
Sample custom configuration options:
--prefix : Specify the install location for the motion package
--with-ffmpeg=[dir] : Specify the location in which ffmpeg/libav is installed.
--without-webp : Compile without webp image support

View File

@@ -9,6 +9,7 @@ To build Motion on FreeBSD, you need the following packages:
* gmake
* libjpeg-turbo
* pkgconf
* libwebp
For database backend support, also install one of the following:
* mysql57-client

View File

@@ -9,7 +9,7 @@ http://brew.sh
Then:
brew install ffmpeg cmake pkg-config libjpeg
brew install ffmpeg cmake pkg-config libjpeg libwebp
cmake .
make

View File

@@ -44,11 +44,11 @@ text_left CAMERA 1
# Recommended to use absolute patch. (Default: current working directory)
#target_dir /tmp/motion/cam1
# File path for motion triggered images (jpeg or ppm) relative to target_dir
# File path for motion triggered images (jpeg, ppm or webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-%q
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q
# File extension .jpg or .ppm is automatically added so do not include this
# File extension .jpg, .ppm or .webp is automatically added so do not include this
# Set to 'preview' together with best-preview feature enables special naming
# convention for preview shots. See motion guide for details
picture_filename CAM1_%v-%Y%m%d%H%M%S-%q
@@ -61,7 +61,7 @@ picture_filename CAM1_%v-%Y%m%d%H%M%S-%q
# The mini-http server listens to this port for requests (default: 0 = disabled)
stream_port 8081
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# Command to be executed when a picture (.ppm|.jpg|.webp) is saved (default: none)
# The filename of the picture is appended as an argument for the command.
#on_picture_save /usr/local/motion-extras/camparse2.pl

View File

@@ -44,11 +44,11 @@ text_left CAMERA 2
# Recommended to use absolute patch. (Default: current working directory)
#target_dir /tmp/motion/cam2
# File path for motion triggered images (jpeg or ppm) relative to target_dir
# File path for motion triggered images (jpeg, ppm or webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-%q
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q
# File extension .jpg or .ppm is automatically added so do not include this
# File extension .jpg, .ppm or .webp is automatically added so do not include this
# Set to 'preview' together with best-preview feature enables special naming
# convention for preview shots. See motion guide for details
picture_filename CAM2_%v-%Y%m%d%H%M%S-%q
@@ -61,7 +61,7 @@ picture_filename CAM2_%v-%Y%m%d%H%M%S-%q
# The mini-http server listens to this port for requests (default: 0 = disabled)
stream_port 8082
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# Command to be executed when a picture (.ppm|.jpg|.webp) is saved (default: none)
# The filename of the picture is appended as an argument for the command.
#on_picture_save /usr/local/motion-extras/camparse2.pl

View File

@@ -44,11 +44,11 @@ text_left CAMERA 3
# Recommended to use absolute patch. (Default: current working directory)
#target_dir /tmp/motion/cam3
# File path for motion triggered images (jpeg or ppm) relative to target_dir
# File path for motion triggered images (jpeg, ppm or webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-%q
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q
# File extension .jpg or .ppm is automatically added so do not include this
# File extension .jpg, .ppm or .webp is automatically added so do not include this
# Set to 'preview' together with best-preview feature enables special naming
# convention for preview shots. See motion guide for details
picture_filename CAM3_%v-%Y%m%d%H%M%S-%q
@@ -61,7 +61,7 @@ picture_filename CAM3_%v-%Y%m%d%H%M%S-%q
# The mini-http server listens to this port for requests (default: 0 = disabled)
stream_port 8083
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# Command to be executed when a picture (.ppm|.jpg|.webp) is saved (default: none)
# The filename of the picture is appended as an argument for the command.
#on_picture_save /usr/local/motion-extras/camparse2.pl

View File

@@ -44,11 +44,11 @@ text_left CAMERA 4
# Recommended to use absolute patch. (Default: current working directory)
#target_dir /tmp/motion/cam4
# File path for motion triggered images (jpeg or ppm) relative to target_dir
# File path for motion triggered images (jpeg, ppm or webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-%q
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q
# File extension .jpg or .ppm is automatically added so do not include this
# File extension .jpg, .ppm or .webp is automatically added so do not include this
# Set to 'preview' together with best-preview feature enables special naming
# convention for preview shots. See motion guide for details
picture_filename CAM4_%v-%Y%m%d%H%M%S-%q
@@ -61,7 +61,7 @@ picture_filename CAM4_%v-%Y%m%d%H%M%S-%q
# The mini-http server listens to this port for requests (default: 0 = disabled)
stream_port 8084
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# Command to be executed when a picture (.ppm|.jpg|.webp) is saved (default: none)
# The filename of the picture is appended as an argument for the command.
#on_picture_save /usr/local/motion-extras/camparse2.pl

14
conf.c
View File

@@ -739,7 +739,7 @@ config_param config_params[] = {
},
{
"quality",
"# The quality (in percent) to be used by the jpeg compression (default: 75)",
"# The quality (in percent) to be used by the jpeg and webp compression (default: 75)",
0,
CONF_OFFSET(quality),
copy_int,
@@ -758,7 +758,7 @@ config_param config_params[] = {
{
"picture_type",
"# Type of output images\n"
"# Valid values: jpeg, ppm (default: jpeg)",
"# Valid values: jpeg, ppm or webp (default: jpeg)",
0,
CONF_OFFSET(picture_type),
copy_string,
@@ -1010,11 +1010,11 @@ config_param config_params[] = {
},
{
"snapshot_filename",
"# File path for snapshots (jpeg or ppm) relative to target_dir\n"
"# File path for snapshots (jpeg, ppm or webp) relative to target_dir\n"
"# Default: "DEF_SNAPPATH"\n"
"# Default value is equivalent to legacy oldlayout option\n"
"# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-snapshot\n"
"# File extension .jpg or .ppm is automatically added so do not include this.\n"
"# File extension .jpg, .ppm or .webp is automatically added so do not include this.\n"
"# Note: A symbolic link called lastsnap.jpg created in the target_dir will always\n"
"# point to the latest snapshot, unless snapshot_filename is exactly 'lastsnap'",
0,
@@ -1024,11 +1024,11 @@ config_param config_params[] = {
},
{
"picture_filename",
"# File path for motion triggered images (jpeg or ppm) relative to target_dir\n"
"# File path for motion triggered images (jpeg, ppm or webp) relative to target_dir\n"
"# Default: "DEF_IMAGEPATH"\n"
"# Default value is equivalent to legacy oldlayout option\n"
"# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q\n"
"# File extension .jpg or .ppm is automatically added so do not include this\n"
"# File extension .jpg, .ppm or .webp is automatically added so do not include this\n"
"# Set to 'preview' together with best-preview feature enables special naming\n"
"# convention for preview shots. See motion guide for details",
0,
@@ -1405,7 +1405,7 @@ config_param config_params[] = {
},
{
"on_picture_save",
"# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)\n"
"# Command to be executed when a picture (.ppm|.jpg|.webp) is saved (default: none)\n"
"# To give the filename as an argument to a command append it with %f",
0,
CONF_OFFSET(on_picture_save),

View File

@@ -338,6 +338,31 @@ AC_CHECK_PROG([PKGCONFIG],[pkg-config],[yes],[no])
AM_CONDITIONAL([FOUND_PKGCONFIG], [test "x$PKGCONFIG" = xyes])
AM_COND_IF([FOUND_PKGCONFIG],,[AC_MSG_ERROR([Required package 'pkg-config' not found, please check motion_guide.html and install necessary dependencies.])])
# Check for the libwebp library
#
AC_ARG_WITH(webp,
[ --without-webp Compile without webp image support],
WEBP="no",
WEBP="yes"
)
HAVE_WEBP=""
if test "${WEBP}" = "yes"; then
AC_MSG_CHECKING(for libwebp)
WEBP_DEPS="libwebp"
if pkg-config $WEBP_DEPS; then
AC_MSG_RESULT(found)
AC_DEFINE([HAVE_WEBP], 1, [Define to 1 if WEBP is around])
HAVE_WEBP="yes"
TEMP_LIBS="$TEMP_LIBS -lwebp -lwebpmux"
else
AC_MSG_RESULT(not found)
AC_MSG_ERROR([Required package 'libwebp-dev' not found. Please check motion_guide.html and install necessary dependencies or use the '--without-webp' configuration option.])
fi
fi
# Check for raspberry pi mmal interface
#
WITHOUT_MMAL="no"
@@ -1080,6 +1105,12 @@ else
echo "**********************************************"
fi
if test "${HAVE_WEBP}" = "yes"; then
echo "webp support: yes"
else
echo "webp support: no"
fi
if test "${FreeBSD}" != ""; then
if test "${BKTR}" = "yes"; then
echo "BKTR included: Yes"

View File

@@ -325,6 +325,9 @@ const char *imageext(struct context *cnt)
if (cnt->imgs.picture_type == IMAGE_TYPE_PPM)
return "ppm";
if (cnt->imgs.picture_type == IMAGE_TYPE_WEBP)
return "webp";
return "jpg";
}

View File

@@ -282,11 +282,11 @@ output_pictures on
# Output pictures with only the pixels moving object (ghost images) (default: off)
output_debug_pictures off
# The quality (in percent) to be used by the jpeg compression (default: 75)
# The quality (in percent) to be used by the jpeg and webp compression (default: 75)
quality 75
# Type of output images
# Valid values: jpeg, ppm (default: jpeg)
# Valid values: jpeg, ppm or webp (default: jpeg)
picture_type jpeg
############################################################
@@ -449,20 +449,20 @@ text_double off
# Recommended to use absolute path. (Default: current working directory)
#target_dir /tmp/motion
# File path for snapshots (jpeg or ppm) relative to target_dir
# File path for snapshots (jpeg, ppm or webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-snapshot
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-snapshot
# File extension .jpg or .ppm is automatically added so do not include this.
# File extension .jpg, .ppm or .webp is automatically added so do not include this.
# Note: A symbolic link called lastsnap.jpg created in the target_dir will always
# point to the latest snapshot, unless snapshot_filename is exactly 'lastsnap'
snapshot_filename %v-%Y%m%d%H%M%S-snapshot
# File path for motion triggered images (jpeg or ppm) relative to target_dir
# File path for motion triggered images (jpeg, ppm or .webp) relative to target_dir
# Default: %v-%Y%m%d%H%M%S-%q
# Default value is equivalent to legacy oldlayout option
# For Motion 3.0 compatible mode choose: %Y/%m/%d/%H/%M/%S-%q
# File extension .jpg or .ppm is automatically added so do not include this
# File extension .jpg, .ppm or .webp is automatically added so do not include this
# Set to 'preview' together with best-preview feature enables special naming
# convention for preview shots. See motion guide for details
picture_filename %v-%Y%m%d%H%M%S-%q

View File

@@ -903,7 +903,7 @@ Default: 75
Description:
.fi
.RS
The quality (in percent) to be used by the jpeg compression
The quality (in percent) to be used by the jpeg and webp compression
.RE
.RE
@@ -911,7 +911,7 @@ The quality (in percent) to be used by the jpeg compression
.B picture_type
.RS
.nf
Values: jpeg/ppm
Values: jpeg/ppm/webp
Default: jpeg
Description:
.fi
@@ -1265,7 +1265,7 @@ Description:
.fi
.RS
The file path for snapshots relative to target_dir.
The file extension .jpg or .ppm is automatically added so do not include this.
The file extension .jpg, .ppm or .webp is automatically added so do not include this.
A symbolic link called lastsnap.jpg created in the target_dir will always
point to the latest snapshot, unless snapshot_filename is exactly 'lastsnap'
This option accepts the conversion specifiers included at the end of this manual.
@@ -1281,8 +1281,8 @@ Default: %v-%Y%m%d%H%M%S-%q
Description:
.fi
.RS
The file path for motion triggered images (jpeg or ppm) relative to target_dir.
The file extension of .jpg or .ppm is automatically added so do not include this.
The file path for motion triggered images (jpeg, ppm or webp) relative to target_dir.
The file extension .jpg, .ppm or .webp is automatically added so do not include this.
Set to 'preview' together with best-preview feature enables special naming
convention for preview shots.
This option accepts the conversion specifiers included at the end of this manual.

View File

@@ -861,6 +861,15 @@ static int motion_init(struct context *cnt)
/* Set output picture type */
if (!strcmp(cnt->conf.picture_type, "ppm"))
cnt->imgs.picture_type = IMAGE_TYPE_PPM;
else if (!strcmp(cnt->conf.picture_type, "webp")) {
#ifdef HAVE_WEBP
cnt->imgs.picture_type = IMAGE_TYPE_WEBP;
#else
/* Fallback to jpeg if webp was selected in the config file, but the support for it was not compiled in */
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s: webp image format is not available, failing back to jpeg");
cnt->imgs.picture_type = IMAGE_TYPE_JPEG;
#endif /* HAVE_WEBP */
}
else
cnt->imgs.picture_type = IMAGE_TYPE_JPEG;

View File

@@ -168,6 +168,7 @@
/* OUTPUT Image types */
#define IMAGE_TYPE_JPEG 0
#define IMAGE_TYPE_PPM 1
#define IMAGE_TYPE_WEBP 2
/* Filetype defines */
#define FTYPE_IMAGE 1

View File

@@ -9,7 +9,7 @@ URL: https://motion-project.github.io/
Source0: https://github.com/Motion-Project/motion
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: libjpeg-devel ffmpeg-devel zlib-devel
BuildRequires: libjpeg-devel ffmpeg-devel zlib-devel libwebp-devel
#This requires comes from the startup script, it will be there until motion supports libv4l calls in the code
Requires: libv4l
Requires(post): chkconfig

View File

@@ -241,7 +241,7 @@ script for Ubuntu. If errors occur during the process or you wish to customize
review the extended building instructions further below.
<p></p>
<code><strong>sudo apt-get install autoconf automake build-essential pkgconf libtool libzip-dev
libjpeg62 libjpeg62-dev git libavformat-dev libavcodec-dev libavutil-dev libswscale-dev</strong></code>
libjpeg62 libjpeg62-dev git libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libwebp-dev</strong></code>
<p></p>
<code><strong>cd ~</strong></code>
<br><code><strong>git clone https://github.com/Motion-Project/motion.git</strong></code>
@@ -277,7 +277,7 @@ Ubuntu / Debian Packages
<li>Required</li>
<ul>
<p></p>
<code><strong>sudo apt-get install autoconf automake build-essential pkgconf libtool git libzip-dev libjpeg62 libjpeg62-dev</strong></code>
<code><strong>sudo apt-get install autoconf automake build-essential pkgconf libtool git libzip-dev libjpeg62 libjpeg62-dev libwebp-dev</strong></code>
<p></p>
</ul>
<p></p>
@@ -336,6 +336,8 @@ openSUSE Packages
<p></p>
<code><strong>sudo zypper install -t pattern devel_C_C++ </strong></code>
<p></p>
<code><strong>sudo zypper install libwebp-devel </strong></code>
<p></p>
</ul>
<p></p>
<li>Optional Packages</li>
@@ -386,6 +388,7 @@ FreeBSD
<li>gcc</li>
<li>gmake</li>
<li>libjpeg-turbo</li>
<li>libwebp</li>
<li>pkgconf</li>
<li>ffmpeg</li>
</ul>
@@ -625,6 +628,11 @@ how Motion is built.
<td bgcolor="#edf4f9" word-wrap:break-word > Specify the prefix for the install path for jpeg-mmx for optimized jpeg handling</td>
<td bgcolor="#edf4f9" word-wrap:break-word > </td>
</tr>
<tr>
<td bgcolor="#edf4f9" word-wrap:break-word > --without-webp </td>
<td bgcolor="#edf4f9" word-wrap:break-word > Compile without webp image support</td>
<td bgcolor="#edf4f9" word-wrap:break-word > </td>
</tr>
<tr>
<td bgcolor="#edf4f9" word-wrap:break-word > --with-ffmpeg=DIR </td>
<td bgcolor="#edf4f9" word-wrap:break-word > Specify the path for the directory prefix in which the
@@ -4052,7 +4060,7 @@ the .jpg or .ppm. E.g. the name can be 01-20020424232936-00m.jpg.
<li> Default: 75</li>
</ul>
<p></p>
The quality for the jpeg images in percent.
The quality for the jpeg or webp images in percent.
100 means hardly compressed. A small number means a much smaller file size but also a less nice
quality image to look at.
<p></p>

View File

@@ -14,6 +14,11 @@
#include <assert.h>
#ifdef HAVE_WEBP
#include <webp/encode.h>
#include <webp/mux.h>
#endif /* HAVE_WEBP */
#include <jpeglib.h>
#include <jerror.h>
@@ -541,6 +546,80 @@ static int put_jpeg_grey_memory(unsigned char *dest_image, int image_size, unsig
return dest_image_size;
}
#ifdef HAVE_WEBP
/**
* put_webp_yuv420p_file
* Converts an YUV420P coded image to a webp image and writes
* it to an already open file.
*
* Inputs:
* - image is the image in YUV420P format.
* - width and height are the dimensions of the image
* - quality is the webp encoding quality 0-100%
*
* Output:
* - The webp is written directly to the file given by the file pointer fp
*
* Returns nothing
*/
static void put_webp_yuv420p_file(FILE *fp,
unsigned char *image, int width, int height,
int quality)
{
/* Create a config present and check for compatible library version */
WebPConfig webp_config;
if (!WebPConfigPreset(&webp_config, WEBP_PRESET_DEFAULT, (float) quality)){
MOTION_LOG(ERR, TYPE_CORE, NO_ERRNO, "libwebp version error");
return;
}
/* Create the input data structure and check for compatible library version */
WebPPicture webp_image;
if (!WebPPictureInit(&webp_image)){
MOTION_LOG(ERR, TYPE_CORE, NO_ERRNO, "libwebp version error");
return;
}
/* Allocate the image buffer based on image width and height */
webp_image.width = width;
webp_image.height = height;
if (!WebPPictureAlloc(&webp_image)){
MOTION_LOG(ERR, TYPE_CORE, NO_ERRNO, "libwebp image buffer allocation error");
return;
}
/* Map the input YUV420P buffer as individual Y, U and V pointers */
webp_image.y = image;
webp_image.u = image + width * height;
webp_image.v = webp_image.u + (width * height) / 4;
/* Setup the memory writting method */
WebPMemoryWriter webp_writer;
WebPMemoryWriterInit(&webp_writer);
webp_image.writer = WebPMemoryWrite;
webp_image.custom_ptr = (void*) &webp_writer;
/* Encode the YUV image as webp */
if (!WebPEncode(&webp_config, &webp_image))
MOTION_LOG(WRN, TYPE_CORE, NO_ERRNO, "libwebp image compression error");
/* Write the webp bytestream to file */
if (fwrite(webp_writer.mem, sizeof(uint8_t), webp_writer.size, fp) != webp_writer.size)
MOTION_LOG(ERR, TYPE_CORE, NO_ERRNO, "unable to save webp image to file");
#if WEBP_ENCODER_ABI_VERSION > 0x0202
/* writer.mem must be freed by calling WebPMemoryWriterClear */
WebPMemoryWriterClear(&webp_writer);
#else
/* writer.mem must be freed by calling 'free(writer.mem)' */
free(webp_writer.mem);
#endif /* WEBP_ENCODER_ABI_VERSION */
/* free the memory used by webp for image object */
WebPPictureFree(&webp_image);
}
#endif /* HAVE_WEBP */
/**
* put_jpeg_yuv420p_file
* Converts an YUV420P coded image to a jpeg image and writes
@@ -918,7 +997,12 @@ void put_picture_fd(struct context *cnt, FILE *picture, unsigned char *image, in
} else {
switch (cnt->imgs.type) {
case VIDEO_PALETTE_YUV420P:
put_jpeg_yuv420p_file(picture, image, cnt->imgs.width, cnt->imgs.height, quality, cnt, &(cnt->current_image->timestamp_tv), &(cnt->current_image->location));
#ifdef HAVE_WEBP
if (cnt->imgs.picture_type == IMAGE_TYPE_WEBP)
put_webp_yuv420p_file(picture, image, cnt->imgs.width, cnt->imgs.height, quality);
#endif /* HAVE_WEBP */
if (cnt->imgs.picture_type == IMAGE_TYPE_JPEG)
put_jpeg_yuv420p_file(picture, image, cnt->imgs.width, cnt->imgs.height, quality, cnt, &(cnt->current_image->timestamp_tv), &(cnt->current_image->location));
break;
case VIDEO_PALETTE_GREY:
put_jpeg_grey_file(picture, image, cnt->imgs.width, cnt->imgs.height, quality);