From 267f056e4940358a63557b97fa724b330dd7f58b Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 15 Jun 2017 15:51:01 +1000 Subject: [PATCH 01/17] Enable hwaccel h264 encoding on raspberry pi Enable hardware accelerated H264 and MPEG4 video encoding on raspberry pi via libopenmax. --- board/raspberrypi/overlay/opt/vc/lib | 1 + board/raspberrypi2/overlay/opt/vc/lib | 1 + board/raspberrypi3/overlay/opt/vc/lib | 1 + configs/raspberrypi_defconfig | 1 + package/ffmpeg/Config.in | 6 +++++ package/ffmpeg/ffmpeg.mk | 5 ++++ package/motion/0003-prefer-omx-encoders.patch | 19 ++++++++++++++ .../motion/0004-h264-best-crf-quality.patch | 25 +++++++++++++++++++ 8 files changed, 59 insertions(+) create mode 120000 board/raspberrypi/overlay/opt/vc/lib create mode 120000 board/raspberrypi2/overlay/opt/vc/lib create mode 120000 board/raspberrypi3/overlay/opt/vc/lib create mode 100644 package/motion/0003-prefer-omx-encoders.patch create mode 100644 package/motion/0004-h264-best-crf-quality.patch diff --git a/board/raspberrypi/overlay/opt/vc/lib b/board/raspberrypi/overlay/opt/vc/lib new file mode 120000 index 00000000000..2e9ebb527e0 --- /dev/null +++ b/board/raspberrypi/overlay/opt/vc/lib @@ -0,0 +1 @@ +../../usr/lib \ No newline at end of file diff --git a/board/raspberrypi2/overlay/opt/vc/lib b/board/raspberrypi2/overlay/opt/vc/lib new file mode 120000 index 00000000000..2e9ebb527e0 --- /dev/null +++ b/board/raspberrypi2/overlay/opt/vc/lib @@ -0,0 +1 @@ +../../usr/lib \ No newline at end of file diff --git a/board/raspberrypi3/overlay/opt/vc/lib b/board/raspberrypi3/overlay/opt/vc/lib new file mode 120000 index 00000000000..2e9ebb527e0 --- /dev/null +++ b/board/raspberrypi3/overlay/opt/vc/lib @@ -0,0 +1 @@ +../../usr/lib \ No newline at end of file diff --git a/configs/raspberrypi_defconfig b/configs/raspberrypi_defconfig index bbf9509333c..7d17de0d7a8 100644 --- a/configs/raspberrypi_defconfig +++ b/configs/raspberrypi_defconfig @@ -29,6 +29,7 @@ BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_SWSCALE=y +BR2_PACKAGE_FFMPEG_RPI_HW_CODECS=y BR2_PACKAGE_LIBWEBCAM=y BR2_PACKAGE_MOTION=y BR2_PACKAGE_STREAMEYE=y diff --git a/package/ffmpeg/Config.in b/package/ffmpeg/Config.in index b5850db7222..187432d49ab 100644 --- a/package/ffmpeg/Config.in +++ b/package/ffmpeg/Config.in @@ -167,6 +167,12 @@ config BR2_PACKAGE_FFMPEG_OUTDEVS bool "Enable output devices" default y +config BR2_PACKAGE_FFMPEG_RPI_HW_CODECS + bool "Enable rpi hardware accelerated codecs" + depends on BR2_PACKAGE_RPI_USERLAND + help + Enable HW accelerated codecs on Raspberry pi. + config BR2_PACKAGE_FFMPEG_EXTRACONF string "Additional parameters for ./configure" default "" diff --git a/package/ffmpeg/ffmpeg.mk b/package/ffmpeg/ffmpeg.mk index 6540d41c525..d9c140d9655 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -473,6 +473,11 @@ else ifneq ($(call qstrip,$(BR2_GCC_TARGET_ARCH)),) FFMPEG_CONF_OPTS += --cpu=$(BR2_GCC_TARGET_ARCH) endif +ifeq ($(BR2_PACKAGE_FFMPEG_RPI_HW_CODECS),y) +FFMPEG_DEPENDENCIES += rpi-userland +FFMPEG_CONF_OPTS += --enable-omx --enable-omx-rpi --enable-mmal --extra-cflags=-I../../staging/usr/include/IL/ +endif + FFMPEG_CONF_OPTS += $(call qstrip,$(BR2_PACKAGE_FFMPEG_EXTRACONF)) diff --git a/package/motion/0003-prefer-omx-encoders.patch b/package/motion/0003-prefer-omx-encoders.patch new file mode 100644 index 00000000000..73d41b63d53 --- /dev/null +++ b/package/motion/0003-prefer-omx-encoders.patch @@ -0,0 +1,19 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index e7cab9f..3f48db8 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -380,7 +380,13 @@ struct ffmpeg *ffmpeg_open(const char *ffmpeg_video_codec, char *filename, + ffmpeg->video_st = NULL; + if (ffmpeg->oc->oformat->video_codec != MY_CODEC_ID_NONE) { + +- codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); ++ codec = NULL; ++ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) ++ codec = avcodec_find_encoder_by_name("h264_omx"); ++ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) ++ codec = avcodec_find_encoder_by_name("mpeg4_omx"); ++ if (!codec) ++ codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); + if (!codec) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Codec %s not found", ffmpeg_video_codec); + ffmpeg_cleanups(ffmpeg); diff --git a/package/motion/0004-h264-best-crf-quality.patch b/package/motion/0004-h264-best-crf-quality.patch new file mode 100644 index 00000000000..d41b32ce597 --- /dev/null +++ b/package/motion/0004-h264-best-crf-quality.patch @@ -0,0 +1,25 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 3f48db8..1819e35 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -419,6 +419,8 @@ struct ffmpeg *ffmpeg_open(const char *ffmpeg_video_codec, char *filename, + c->codec_id = ffmpeg->oc->oformat->video_codec; + c->codec_type = AVMEDIA_TYPE_VIDEO; + c->bit_rate = bps; ++ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) ++ av_opt_set(c->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN); + c->width = width; + c->height = height; + c->time_base.num = 1; +diff --git a/ffmpeg.h b/ffmpeg.h +index ccdc0f1..7067569 100644 +--- a/ffmpeg.h ++++ b/ffmpeg.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #if (LIBAVFORMAT_VERSION_MAJOR >= 56) + From 5e4b50b8a210b677ba27a176cf30af4c70458b9b Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 20 Jun 2017 11:24:39 +1000 Subject: [PATCH 02/17] motion: bump version --- package/motion/0003-prefer-omx-encoders.patch | 19 -------------- .../motion/0004-h264-best-crf-quality.patch | 25 ------------------- package/motion/motion.mk | 3 +-- 3 files changed, 1 insertion(+), 46 deletions(-) delete mode 100644 package/motion/0003-prefer-omx-encoders.patch delete mode 100644 package/motion/0004-h264-best-crf-quality.patch diff --git a/package/motion/0003-prefer-omx-encoders.patch b/package/motion/0003-prefer-omx-encoders.patch deleted file mode 100644 index 73d41b63d53..00000000000 --- a/package/motion/0003-prefer-omx-encoders.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index e7cab9f..3f48db8 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -380,7 +380,13 @@ struct ffmpeg *ffmpeg_open(const char *ffmpeg_video_codec, char *filename, - ffmpeg->video_st = NULL; - if (ffmpeg->oc->oformat->video_codec != MY_CODEC_ID_NONE) { - -- codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); -+ codec = NULL; -+ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) -+ codec = avcodec_find_encoder_by_name("h264_omx"); -+ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) -+ codec = avcodec_find_encoder_by_name("mpeg4_omx"); -+ if (!codec) -+ codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); - if (!codec) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Codec %s not found", ffmpeg_video_codec); - ffmpeg_cleanups(ffmpeg); diff --git a/package/motion/0004-h264-best-crf-quality.patch b/package/motion/0004-h264-best-crf-quality.patch deleted file mode 100644 index d41b32ce597..00000000000 --- a/package/motion/0004-h264-best-crf-quality.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 3f48db8..1819e35 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -419,6 +419,8 @@ struct ffmpeg *ffmpeg_open(const char *ffmpeg_video_codec, char *filename, - c->codec_id = ffmpeg->oc->oformat->video_codec; - c->codec_type = AVMEDIA_TYPE_VIDEO; - c->bit_rate = bps; -+ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) -+ av_opt_set(c->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN); - c->width = width; - c->height = height; - c->time_base.num = 1; -diff --git a/ffmpeg.h b/ffmpeg.h -index ccdc0f1..7067569 100644 ---- a/ffmpeg.h -+++ b/ffmpeg.h -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #if (LIBAVFORMAT_VERSION_MAJOR >= 56) - diff --git a/package/motion/motion.mk b/package/motion/motion.mk index f3815e37a43..70ffcf7c312 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -4,7 +4,7 @@ # ################################################################################ -MOTION_VERSION = 37b3595 +MOTION_VERSION = 9fa9d22473899f654922174db0c474e14738a833 MOTION_SITE = $(call github,motion-project,motion,$(MOTION_VERSION)) MOTION_AUTORECONF = YES MOTION_CONF_OPTS = --without-pgsql --without-sdl --without-sqlite3 --without-mysql --with-ffmpeg=$(STAGING_DIR)/usr/lib \ @@ -15,4 +15,3 @@ define MOTION_INSTALL_TARGET_CMDS endef $(eval $(autotools-package)) - From 3e76cb2c34833145e56e72f5ad04565b79a4d60d Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 20 Jun 2017 11:29:29 +1000 Subject: [PATCH 03/17] motion: prefer OMX H264 encoder motion prefers OMX H264 encoder, but falls back to software encoder. --- package/motion/prefer-omx-encoders.patch | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 package/motion/prefer-omx-encoders.patch diff --git a/package/motion/prefer-omx-encoders.patch b/package/motion/prefer-omx-encoders.patch new file mode 100644 index 00000000000..b3f778e9505 --- /dev/null +++ b/package/motion/prefer-omx-encoders.patch @@ -0,0 +1,24 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 30a9cde..829d5a2 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -484,7 +484,13 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ + char errstr[128]; + int chkrate; + +- ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); ++ ffmpeg->codec = NULL; ++ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) ++ ffmpeg->codec = avcodec_find_encoder_by_name("h264_omx"); ++ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) ++ ffmpeg->codec = avcodec_find_encoder_by_name("mpeg4_omx"); ++ if (!ffmpeg->codec) ++ ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); + if (!ffmpeg->codec) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Codec %s not found", ffmpeg->codec_name); + ffmpeg_free_context(ffmpeg); +@@ -926,4 +932,3 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, unsigned char *image, const struct t + return 0; + #endif // HAVE_FFMPEG + } +- From c1ed4cf8075beb2ce098027ec35693ba0b3eaec8 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 20 Jun 2017 11:32:39 +1000 Subject: [PATCH 04/17] motion: h264 encoder respects quality settings --- package/motion/tune-h264-encode-quality.patch | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 package/motion/tune-h264-encode-quality.patch diff --git a/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch new file mode 100644 index 00000000000..29d561b3d9a --- /dev/null +++ b/package/motion/tune-h264-encode-quality.patch @@ -0,0 +1,33 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 8f66121..9634a20 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -451,20 +451,27 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ + + char crf[4]; ++ int bit_rate; + + ffmpeg->opts = 0; + if (ffmpeg->vbr > 100) ffmpeg->vbr = 100; + if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || + ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ + if (ffmpeg->vbr > 0) { ++ if (ffmpeg->vbr < 10) ffmpeg->vbr = 10; ++ //bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ++ bit_rate = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 8; + ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); + } else { ++ bit_rate = ffmpeg->bps; + ffmpeg->vbr = 28; + } + snprintf(crf, 4, "%d",ffmpeg->vbr); +- av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); ++ av_dict_set(&ffmpeg->opts, "preset", "slow", 0); + av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); + av_dict_set(&ffmpeg->opts, "crf", crf, 0); ++ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; ++ ffmpeg->ctx_codec->bit_rate = bit_rate; + } else { + /* The selection of 8000 in the else is a subjective number based upon viewing output files */ + if (ffmpeg->vbr > 0){ From 414420b917d63a05e6b111c167ee3e778e837156 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 21 Jun 2017 13:07:17 +1000 Subject: [PATCH 05/17] enable ffmpeg hwaccel on rpi2 rpi3 --- configs/raspberrypi2_defconfig | 1 + configs/raspberrypi3_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/raspberrypi2_defconfig b/configs/raspberrypi2_defconfig index 871aa5ec8c5..3b6c7fe1ef2 100644 --- a/configs/raspberrypi2_defconfig +++ b/configs/raspberrypi2_defconfig @@ -27,6 +27,7 @@ BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_SWSCALE=y +BR2_PACKAGE_FFMPEG_RPI_HW_CODECS=y BR2_PACKAGE_LIBWEBCAM=y BR2_PACKAGE_MOTION=y BR2_PACKAGE_STREAMEYE=y diff --git a/configs/raspberrypi3_defconfig b/configs/raspberrypi3_defconfig index 9a68f6f1b08..7aa8e089a91 100644 --- a/configs/raspberrypi3_defconfig +++ b/configs/raspberrypi3_defconfig @@ -27,6 +27,7 @@ BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_SWSCALE=y +BR2_PACKAGE_FFMPEG_RPI_HW_CODECS=y BR2_PACKAGE_LIBWEBCAM=y BR2_PACKAGE_MOTION=y BR2_PACKAGE_STREAMEYE=y From 28454d80ade847562bd3a1038ea2f33f36f5f8cc Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 31 Jul 2017 12:11:43 +1000 Subject: [PATCH 06/17] ffmpeg: upgrade to version 3.3.2 --- package/ffmpeg/ffmpeg.hash | 1 + package/ffmpeg/ffmpeg.mk | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package/ffmpeg/ffmpeg.hash b/package/ffmpeg/ffmpeg.hash index 6adf7e440a2..77e185f5ed5 100644 --- a/package/ffmpeg/ffmpeg.hash +++ b/package/ffmpeg/ffmpeg.hash @@ -1,2 +1,3 @@ # Locally calculated sha256 54ce502aca10b7e6059f19220ea2f68fa0c9c4c4d255ae13e615f08f0c94dcc5 ffmpeg-3.2.3.tar.xz +sha256 1998de1ab32616cbf2ff86efc3f1f26e76805ec5dc51e24c041c79edd8262785 ffmpeg-3.3.2.tar.xz diff --git a/package/ffmpeg/ffmpeg.mk b/package/ffmpeg/ffmpeg.mk index d9c140d9655..4bdd9e6f509 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -4,7 +4,7 @@ # ################################################################################ -FFMPEG_VERSION = 3.2.3 +FFMPEG_VERSION = 3.3.2 FFMPEG_SOURCE = ffmpeg-$(FFMPEG_VERSION).tar.xz FFMPEG_SITE = http://ffmpeg.org/releases FFMPEG_INSTALL_STAGING = YES @@ -26,7 +26,6 @@ FFMPEG_CONF_OPTS = \ --enable-avdevice \ --enable-avcodec \ --enable-avformat \ - --disable-x11grab \ --enable-network \ --disable-gray \ --enable-swscale-alpha \ @@ -39,7 +38,6 @@ FFMPEG_CONF_OPTS = \ --disable-dxva2 \ --enable-runtime-cpudetect \ --disable-hardcoded-tables \ - --disable-memalign-hack \ --disable-mipsdsp \ --disable-mipsdspr2 \ --disable-msa \ From 2a3f6e7b1eaebb274f044657c3c9b122301c487c Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 31 Jul 2017 12:12:01 +1000 Subject: [PATCH 07/17] motion: upgrade to latest master --- package/motion/motion.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/motion/motion.mk b/package/motion/motion.mk index 70ffcf7c312..f783053cef5 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -4,7 +4,7 @@ # ################################################################################ -MOTION_VERSION = 9fa9d22473899f654922174db0c474e14738a833 +MOTION_VERSION = e9e0a2d29205956055dd5ba7ca0cb52b585f182a MOTION_SITE = $(call github,motion-project,motion,$(MOTION_VERSION)) MOTION_AUTORECONF = YES MOTION_CONF_OPTS = --without-pgsql --without-sdl --without-sqlite3 --without-mysql --with-ffmpeg=$(STAGING_DIR)/usr/lib \ From 9fd9a6f8cacba19e327fa39b8ef8d47fffeb03dd Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Fri, 4 Aug 2017 14:53:24 +1000 Subject: [PATCH 08/17] motion: bumped to latest master --- package/motion/motion.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/motion/motion.mk b/package/motion/motion.mk index f783053cef5..b8f6004813a 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -4,7 +4,7 @@ # ################################################################################ -MOTION_VERSION = e9e0a2d29205956055dd5ba7ca0cb52b585f182a +MOTION_VERSION = ab9e800d5984f2907f00bebabc794d1dba9682ad MOTION_SITE = $(call github,motion-project,motion,$(MOTION_VERSION)) MOTION_AUTORECONF = YES MOTION_CONF_OPTS = --without-pgsql --without-sdl --without-sqlite3 --without-mysql --with-ffmpeg=$(STAGING_DIR)/usr/lib \ From e0514485099a7adc8e37dfc7047bb387bf261fab Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Fri, 4 Aug 2017 14:52:53 +1000 Subject: [PATCH 09/17] don't use h264_omx via C API, use extpipe instead motion interfacing with ffmpeg C API proved to be unstable. --- package/motion/prefer-omx-encoders.patch | 24 -------------- package/motion/tune-h264-encode-quality.patch | 33 ------------------- .../allow-extpipe-motion-option.patch | 19 +++++++++++ 3 files changed, 19 insertions(+), 57 deletions(-) delete mode 100644 package/motion/prefer-omx-encoders.patch delete mode 100644 package/motion/tune-h264-encode-quality.patch create mode 100644 package/motioneye/allow-extpipe-motion-option.patch diff --git a/package/motion/prefer-omx-encoders.patch b/package/motion/prefer-omx-encoders.patch deleted file mode 100644 index b3f778e9505..00000000000 --- a/package/motion/prefer-omx-encoders.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 30a9cde..829d5a2 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -484,7 +484,13 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ - char errstr[128]; - int chkrate; - -- ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); -+ ffmpeg->codec = NULL; -+ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) -+ ffmpeg->codec = avcodec_find_encoder_by_name("h264_omx"); -+ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) -+ ffmpeg->codec = avcodec_find_encoder_by_name("mpeg4_omx"); -+ if (!ffmpeg->codec) -+ ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); - if (!ffmpeg->codec) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Codec %s not found", ffmpeg->codec_name); - ffmpeg_free_context(ffmpeg); -@@ -926,4 +932,3 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, unsigned char *image, const struct t - return 0; - #endif // HAVE_FFMPEG - } -- diff --git a/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch deleted file mode 100644 index 29d561b3d9a..00000000000 --- a/package/motion/tune-h264-encode-quality.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 8f66121..9634a20 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -451,20 +451,27 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ - - char crf[4]; -+ int bit_rate; - - ffmpeg->opts = 0; - if (ffmpeg->vbr > 100) ffmpeg->vbr = 100; - if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || - ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ - if (ffmpeg->vbr > 0) { -+ if (ffmpeg->vbr < 10) ffmpeg->vbr = 10; -+ //bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor -+ bit_rate = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 8; - ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); - } else { -+ bit_rate = ffmpeg->bps; - ffmpeg->vbr = 28; - } - snprintf(crf, 4, "%d",ffmpeg->vbr); -- av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); -+ av_dict_set(&ffmpeg->opts, "preset", "slow", 0); - av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); - av_dict_set(&ffmpeg->opts, "crf", crf, 0); -+ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; -+ ffmpeg->ctx_codec->bit_rate = bit_rate; - } else { - /* The selection of 8000 in the else is a subjective number based upon viewing output files */ - if (ffmpeg->vbr > 0){ diff --git a/package/motioneye/allow-extpipe-motion-option.patch b/package/motioneye/allow-extpipe-motion-option.patch new file mode 100644 index 00000000000..f77bff853ab --- /dev/null +++ b/package/motioneye/allow-extpipe-motion-option.patch @@ -0,0 +1,19 @@ +commit 7a916dea0c90f7040ce3c5a78da560edc4d9ba53 +Author: Joo Aun Saw +Date: Fri Aug 4 14:36:04 2017 +1000 + + allow extpipe motion option + +diff --git a/motioneye/config.py b/motioneye/config.py +index 48e8cf5..1b1b087 100644 +--- a/motioneye/config.py ++++ b/motioneye/config.py +@@ -118,6 +118,8 @@ _KNOWN_MOTION_OPTIONS = set([ + 'threshold', + 'videodevice', + 'width', ++ 'use_extpipe', ++ 'extpipe', + ]) + + From 0008c743e4164075502ec0ee04b64448cae7decb Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 7 Aug 2017 12:12:19 +1000 Subject: [PATCH 10/17] motioneye: Use extpipe ffmpeg h264_omx encoder --- .../allow-extpipe-motion-option.patch | 19 ---- ...use-extpipe-ffmpeg-h264-omx-encoding.patch | 94 +++++++++++++++++++ 2 files changed, 94 insertions(+), 19 deletions(-) delete mode 100644 package/motioneye/allow-extpipe-motion-option.patch create mode 100644 package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch diff --git a/package/motioneye/allow-extpipe-motion-option.patch b/package/motioneye/allow-extpipe-motion-option.patch deleted file mode 100644 index f77bff853ab..00000000000 --- a/package/motioneye/allow-extpipe-motion-option.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit 7a916dea0c90f7040ce3c5a78da560edc4d9ba53 -Author: Joo Aun Saw -Date: Fri Aug 4 14:36:04 2017 +1000 - - allow extpipe motion option - -diff --git a/motioneye/config.py b/motioneye/config.py -index 48e8cf5..1b1b087 100644 ---- a/motioneye/config.py -+++ b/motioneye/config.py -@@ -118,6 +118,8 @@ _KNOWN_MOTION_OPTIONS = set([ - 'threshold', - 'videodevice', - 'width', -+ 'use_extpipe', -+ 'extpipe', - ]) - - diff --git a/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch b/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch new file mode 100644 index 00000000000..129ae756775 --- /dev/null +++ b/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch @@ -0,0 +1,94 @@ +commit d6b2e8203453c75e3b64a441a66091d9a099f31e +Author: Joo Aun Saw +Date: Mon Aug 7 12:09:04 2017 +1000 + + Use extpipe ffmpeg h264_omx encoder + + Use ffmpeg h264_omx hardware accelerated encoder via extpipe when output + video format is H264. Applies to mp4 and mkv containers. + +diff --git a/motioneye/config.py b/motioneye/config.py +index 48e8cf5..ddf10c9 100644 +--- a/motioneye/config.py ++++ b/motioneye/config.py +@@ -58,6 +58,10 @@ _EXPONENTIAL_QUALITY_FACTOR = 100000 # voodoo + _EXPONENTIAL_DEF_QUALITY = 511 # about 75% + _MAX_FFMPEG_VARIABLE_BITRATE = 32767 + ++_EXTPIPE_FFMPEG_H264_OMX_CODEC = {'mp4', 'mkv'} ++_EXTPIPE_FFMPEG_H264_OMX_CODEC_ARGS = {'mp4':'-f mp4 %f.mp4', 'mkv':'-f matroska %f.mkv'} ++_EXTPIPE_FFMPEG_H264_OMX_CMD = 'ffmpeg -y -f rawvideo -pix_fmt yuv420p -video_size %wx%h -framerate %fps -i pipe:0 -c:v h264_omx -profile:v high -b:v 3000000' ++ + _KNOWN_MOTION_OPTIONS = set([ + 'auto_brightness', + 'brightness', +@@ -118,6 +122,8 @@ _KNOWN_MOTION_OPTIONS = set([ + 'threshold', + 'videodevice', + 'width', ++ 'use_extpipe', ++ 'extpipe', + ]) + + +@@ -737,6 +743,8 @@ def motion_camera_ui_to_dict(ui, old_config=None): + 'movie_filename': ui['movie_file_name'], + 'max_movie_time': ui['max_movie_length'], + '@preserve_movies': int(ui['preserve_movies']), ++ 'use_extpipe': False, ++ 'extpipe': '', + + # motion detection + '@motion_detection': ui['motion_detection'], +@@ -919,6 +927,11 @@ def motion_camera_ui_to_dict(ui, old_config=None): + elif recording_mode == 'continuous': + data['emulate_motion'] = True + ++ if ui['movie_format'] in _EXTPIPE_FFMPEG_H264_OMX_CODEC: ++ data['ffmpeg_output_movies'] = False ++ data['use_extpipe'] = True ++ data['extpipe'] = _EXTPIPE_FFMPEG_H264_OMX_CMD + ' ' + _EXTPIPE_FFMPEG_H264_OMX_CODEC_ARGS[ui['movie_format']] ++ + data['ffmpeg_video_codec'] = ui['movie_format'] + q = int(ui['movie_quality']) + if motionctl.needs_ffvb_quirks(): +@@ -1120,6 +1133,8 @@ def motion_camera_dict_to_ui(data): + 'movie_file_name': data['movie_filename'], + 'max_movie_length': data['max_movie_time'], + 'preserve_movies': data['@preserve_movies'], ++ 'use_extpipe': False, ++ 'extpipe': '', + + # motion detection + 'motion_detection': data['@motion_detection'], +@@ -1303,7 +1318,7 @@ def motion_camera_dict_to_ui(data): + if picture_filename: + ui['image_file_name'] = picture_filename + +- if data['ffmpeg_output_movies']: ++ if data['ffmpeg_output_movies'] or data['use_extpipe']: + ui['movies'] = True + + if emulate_motion: +@@ -1883,6 +1898,8 @@ def _set_default_motion_camera(camera_id, data): + + data.setdefault('movie_filename', '%Y-%m-%d/%H-%M-%S') + data.setdefault('max_movie_time', 0) ++ data.setdefault('use_extpipe', False) ++ data.setdefault('extpipe', '') + data.setdefault('ffmpeg_output_movies', False) + if motionctl.has_new_movie_format_support(): + data.setdefault('ffmpeg_video_codec', 'mp4') # will use h264 codec +diff --git a/motioneye/mediafiles.py b/motioneye/mediafiles.py +index 680cdd9..cc54008 100644 +--- a/motioneye/mediafiles.py ++++ b/motioneye/mediafiles.py +@@ -216,7 +216,7 @@ def cleanup_media(media_type): + ((camera_config['emulate_motion'] or camera_config['output_pictures']) and camera_config['picture_filename']) or + (camera_config['snapshot_interval'] and camera_config['snapshot_filename'])) + +- movies_enabled = camera_config['ffmpeg_output_movies'] ++ movies_enabled = camera_config['ffmpeg_output_movies'] or camera_config['use_extpipe'] + + if media_type == 'picture' and not still_images_enabled: + continue # only cleanup pictures for cameras with still images enabled From 7f6c18934cc049aa64caebb2edb3a360bfbf7cbe Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 7 Aug 2017 14:05:54 +1000 Subject: [PATCH 11/17] rpi-firmware: bumped to latest version --- package/rpi-firmware/rpi-firmware.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/rpi-firmware/rpi-firmware.mk b/package/rpi-firmware/rpi-firmware.mk index 401a69f3221..43bd68d6587 100644 --- a/package/rpi-firmware/rpi-firmware.mk +++ b/package/rpi-firmware/rpi-firmware.mk @@ -4,7 +4,7 @@ # ################################################################################ -RPI_FIRMWARE_VERSION = b51046a2b2bb69771579a549d157205d9982f858 +RPI_FIRMWARE_VERSION = 6ba0dabbe76ce02d261cc4658c3484fa12b10385 RPI_FIRMWARE_SITE = $(call github,raspberrypi,firmware,$(RPI_FIRMWARE_VERSION)) RPI_FIRMWARE_LICENSE = BSD-3c RPI_FIRMWARE_LICENSE_FILES = boot/LICENCE.broadcom From 10ede33068e601d0e36522e672a8e0eead395daf Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 9 Aug 2017 11:36:42 +1000 Subject: [PATCH 12/17] motion: temporary fix for extpipe subdir --- .../temp-fix-for-extpipe-subdir-creation.patch | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 package/motion/temp-fix-for-extpipe-subdir-creation.patch diff --git a/package/motion/temp-fix-for-extpipe-subdir-creation.patch b/package/motion/temp-fix-for-extpipe-subdir-creation.patch new file mode 100644 index 00000000000..06637cc1d61 --- /dev/null +++ b/package/motion/temp-fix-for-extpipe-subdir-creation.patch @@ -0,0 +1,17 @@ +diff --git a/event.c b/event.c +index f67214e..44d8096 100644 +--- a/event.c ++++ b/event.c +@@ -572,6 +572,12 @@ static void event_create_extpipe(struct context *cnt, + } + } + ++ /* Temporary solution for https://github.com/Motion-Project/motion/issues/360#issuecomment-320849158 ++ Always create any path specified as file name */ ++ if (create_path(cnt->extpipefilename) == -1) ++ return ; ++ /* end of fix */ ++ + mystrftime(cnt, stamp, sizeof(stamp), cnt->conf.extpipe, currenttime_tv, cnt->extpipefilename, 0); + + MOTION_LOG(NTC, TYPE_EVENTS, NO_ERRNO, "pipe: %s", stamp); From 6c980d667cc8ad33cdb7bc4955f7130bbf3cd0fb Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 15 Aug 2017 13:16:09 +1000 Subject: [PATCH 13/17] disable ffmpeg zerocopy, motion not use extpipe --- .../disable-rpi-omx-input-zerocopy.patch | 15 +++ package/motion/prefer-omx-encoder.patch | 19 ++++ package/motion/tune-h264-encode-quality.patch | 39 ++++++++ ...use-extpipe-ffmpeg-h264-omx-encoding.patch | 94 ------------------- 4 files changed, 73 insertions(+), 94 deletions(-) create mode 100644 package/ffmpeg/disable-rpi-omx-input-zerocopy.patch create mode 100644 package/motion/prefer-omx-encoder.patch create mode 100644 package/motion/tune-h264-encode-quality.patch delete mode 100644 package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch diff --git a/package/ffmpeg/disable-rpi-omx-input-zerocopy.patch b/package/ffmpeg/disable-rpi-omx-input-zerocopy.patch new file mode 100644 index 00000000000..6733d8bafc8 --- /dev/null +++ b/package/ffmpeg/disable-rpi-omx-input-zerocopy.patch @@ -0,0 +1,15 @@ +diff --git a/libavcodec/omx.c b/libavcodec/omx.c +index 19b4f33836..4641dc79e2 100644 +--- a/libavcodec/omx.c ++++ b/libavcodec/omx.c +@@ -644,10 +644,6 @@ static av_cold int omx_encode_init(AVCodecContext *avctx) + OMX_BUFFERHEADERTYPE *buffer; + OMX_ERRORTYPE err; + +-#if CONFIG_OMX_RPI +- s->input_zerocopy = 1; +-#endif +- + s->omx_context = omx_init(avctx, s->libname, s->libprefix); + if (!s->omx_context) + return AVERROR_ENCODER_NOT_FOUND; diff --git a/package/motion/prefer-omx-encoder.patch b/package/motion/prefer-omx-encoder.patch new file mode 100644 index 00000000000..ac07f48d472 --- /dev/null +++ b/package/motion/prefer-omx-encoder.patch @@ -0,0 +1,19 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 71685a1..07ce41c 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -485,7 +485,13 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ + char errstr[128]; + int chkrate; + +- ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); ++ ffmpeg->codec = NULL; ++ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) ++ ffmpeg->codec = avcodec_find_encoder_by_name("h264_omx"); ++ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) ++ ffmpeg->codec = avcodec_find_encoder_by_name("mpeg4_omx"); ++ if (!ffmpeg->codec) ++ ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); + if (!ffmpeg->codec) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Codec %s not found", ffmpeg->codec_name); + ffmpeg_free_context(ffmpeg); diff --git a/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch new file mode 100644 index 00000000000..0f78b6fc78d --- /dev/null +++ b/package/motion/tune-h264-encode-quality.patch @@ -0,0 +1,39 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index a4d3757..124b41f 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -451,21 +451,29 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + + static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ + +- char crf[4]; ++ int bit_rate; + + ffmpeg->opts = 0; + if (ffmpeg->vbr > 100) ffmpeg->vbr = 100; + if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || + ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ + if (ffmpeg->vbr > 0) { ++ if (ffmpeg->vbr < 10) ffmpeg->vbr = 10; ++ //bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ++ bit_rate = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 8; + ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); + } else { ++ bit_rate = ffmpeg->bps; + ffmpeg->vbr = 28; + } +- snprintf(crf, 4, "%d",ffmpeg->vbr); +- av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); +- av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); +- av_dict_set(&ffmpeg->opts, "crf", crf, 0); ++ // Clip to max bit rate ++ if (bit_rate > 2500000) ++ bit_rate = 2500000; ++ av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); ++ av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); ++ av_dict_set_int(&ffmpeg->opts, "crf", ffmpeg->vbr, 0); ++ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; ++ ffmpeg->ctx_codec->bit_rate = bit_rate; + } else { + /* The selection of 8000 in the else is a subjective number based upon viewing output files */ + if (ffmpeg->vbr > 0){ diff --git a/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch b/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch deleted file mode 100644 index 129ae756775..00000000000 --- a/package/motioneye/use-extpipe-ffmpeg-h264-omx-encoding.patch +++ /dev/null @@ -1,94 +0,0 @@ -commit d6b2e8203453c75e3b64a441a66091d9a099f31e -Author: Joo Aun Saw -Date: Mon Aug 7 12:09:04 2017 +1000 - - Use extpipe ffmpeg h264_omx encoder - - Use ffmpeg h264_omx hardware accelerated encoder via extpipe when output - video format is H264. Applies to mp4 and mkv containers. - -diff --git a/motioneye/config.py b/motioneye/config.py -index 48e8cf5..ddf10c9 100644 ---- a/motioneye/config.py -+++ b/motioneye/config.py -@@ -58,6 +58,10 @@ _EXPONENTIAL_QUALITY_FACTOR = 100000 # voodoo - _EXPONENTIAL_DEF_QUALITY = 511 # about 75% - _MAX_FFMPEG_VARIABLE_BITRATE = 32767 - -+_EXTPIPE_FFMPEG_H264_OMX_CODEC = {'mp4', 'mkv'} -+_EXTPIPE_FFMPEG_H264_OMX_CODEC_ARGS = {'mp4':'-f mp4 %f.mp4', 'mkv':'-f matroska %f.mkv'} -+_EXTPIPE_FFMPEG_H264_OMX_CMD = 'ffmpeg -y -f rawvideo -pix_fmt yuv420p -video_size %wx%h -framerate %fps -i pipe:0 -c:v h264_omx -profile:v high -b:v 3000000' -+ - _KNOWN_MOTION_OPTIONS = set([ - 'auto_brightness', - 'brightness', -@@ -118,6 +122,8 @@ _KNOWN_MOTION_OPTIONS = set([ - 'threshold', - 'videodevice', - 'width', -+ 'use_extpipe', -+ 'extpipe', - ]) - - -@@ -737,6 +743,8 @@ def motion_camera_ui_to_dict(ui, old_config=None): - 'movie_filename': ui['movie_file_name'], - 'max_movie_time': ui['max_movie_length'], - '@preserve_movies': int(ui['preserve_movies']), -+ 'use_extpipe': False, -+ 'extpipe': '', - - # motion detection - '@motion_detection': ui['motion_detection'], -@@ -919,6 +927,11 @@ def motion_camera_ui_to_dict(ui, old_config=None): - elif recording_mode == 'continuous': - data['emulate_motion'] = True - -+ if ui['movie_format'] in _EXTPIPE_FFMPEG_H264_OMX_CODEC: -+ data['ffmpeg_output_movies'] = False -+ data['use_extpipe'] = True -+ data['extpipe'] = _EXTPIPE_FFMPEG_H264_OMX_CMD + ' ' + _EXTPIPE_FFMPEG_H264_OMX_CODEC_ARGS[ui['movie_format']] -+ - data['ffmpeg_video_codec'] = ui['movie_format'] - q = int(ui['movie_quality']) - if motionctl.needs_ffvb_quirks(): -@@ -1120,6 +1133,8 @@ def motion_camera_dict_to_ui(data): - 'movie_file_name': data['movie_filename'], - 'max_movie_length': data['max_movie_time'], - 'preserve_movies': data['@preserve_movies'], -+ 'use_extpipe': False, -+ 'extpipe': '', - - # motion detection - 'motion_detection': data['@motion_detection'], -@@ -1303,7 +1318,7 @@ def motion_camera_dict_to_ui(data): - if picture_filename: - ui['image_file_name'] = picture_filename - -- if data['ffmpeg_output_movies']: -+ if data['ffmpeg_output_movies'] or data['use_extpipe']: - ui['movies'] = True - - if emulate_motion: -@@ -1883,6 +1898,8 @@ def _set_default_motion_camera(camera_id, data): - - data.setdefault('movie_filename', '%Y-%m-%d/%H-%M-%S') - data.setdefault('max_movie_time', 0) -+ data.setdefault('use_extpipe', False) -+ data.setdefault('extpipe', '') - data.setdefault('ffmpeg_output_movies', False) - if motionctl.has_new_movie_format_support(): - data.setdefault('ffmpeg_video_codec', 'mp4') # will use h264 codec -diff --git a/motioneye/mediafiles.py b/motioneye/mediafiles.py -index 680cdd9..cc54008 100644 ---- a/motioneye/mediafiles.py -+++ b/motioneye/mediafiles.py -@@ -216,7 +216,7 @@ def cleanup_media(media_type): - ((camera_config['emulate_motion'] or camera_config['output_pictures']) and camera_config['picture_filename']) or - (camera_config['snapshot_interval'] and camera_config['snapshot_filename'])) - -- movies_enabled = camera_config['ffmpeg_output_movies'] -+ movies_enabled = camera_config['ffmpeg_output_movies'] or camera_config['use_extpipe'] - - if media_type == 'picture' and not still_images_enabled: - continue # only cleanup pictures for cameras with still images enabled From 6ba62abe6425e30911b934cc461421df9c7a615a Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 17 Aug 2017 12:56:33 +1000 Subject: [PATCH 14/17] motion: only tune h264_omx encode quality --- package/motion/tune-h264-encode-quality.patch | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch index 0f78b6fc78d..994754f022a 100644 --- a/package/motion/tune-h264-encode-quality.patch +++ b/package/motion/tune-h264-encode-quality.patch @@ -1,8 +1,8 @@ diff --git a/ffmpeg.c b/ffmpeg.c -index a4d3757..124b41f 100644 +index a4d3757..368c855 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -451,21 +451,29 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +@@ -451,7 +451,7 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ @@ -11,13 +11,12 @@ index a4d3757..124b41f 100644 ffmpeg->opts = 0; if (ffmpeg->vbr > 100) ffmpeg->vbr = 100; - if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || +@@ -459,13 +459,24 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ if (ffmpeg->vbr > 0) { -+ if (ffmpeg->vbr < 10) ffmpeg->vbr = 10; + ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); + //bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor + bit_rate = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 8; - ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); } else { + bit_rate = ffmpeg->bps; ffmpeg->vbr = 28; @@ -26,14 +25,18 @@ index a4d3757..124b41f 100644 - av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); - av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); - av_dict_set(&ffmpeg->opts, "crf", crf, 0); -+ // Clip to max bit rate -+ if (bit_rate > 2500000) -+ bit_rate = 2500000; + av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); + av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); + av_dict_set_int(&ffmpeg->opts, "crf", ffmpeg->vbr, 0); -+ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; -+ ffmpeg->ctx_codec->bit_rate = bit_rate; ++ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0)) { ++ // Clip bit rate to min and max ++ if (bit_rate < 40000) ++ bit_rate = 40000; ++ else if (bit_rate > 3000000) ++ bit_rate = 3000000; ++ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; ++ ffmpeg->ctx_codec->bit_rate = bit_rate; ++ } } else { /* The selection of 8000 in the else is a subjective number based upon viewing output files */ if (ffmpeg->vbr > 0){ From 23a77f1f99ba69b92215befa5c8c94adad3cfcf1 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 17 Aug 2017 13:12:21 +1000 Subject: [PATCH 15/17] motion: undo unnecessary blank line removal --- package/motion/motion.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/package/motion/motion.mk b/package/motion/motion.mk index b8f6004813a..46479cf5725 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -15,3 +15,4 @@ define MOTION_INSTALL_TARGET_CMDS endef $(eval $(autotools-package)) + From 77833130258a0ef895cfb78a08f475160d426a7c Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 23 Aug 2017 16:18:10 +1000 Subject: [PATCH 16/17] motion: hwaccel enabled via config file --- package/motion/prefer-omx-encoder.patch | 19 ---- package/motion/preferred-encoder.patch | 145 ++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 19 deletions(-) delete mode 100644 package/motion/prefer-omx-encoder.patch create mode 100644 package/motion/preferred-encoder.patch diff --git a/package/motion/prefer-omx-encoder.patch b/package/motion/prefer-omx-encoder.patch deleted file mode 100644 index ac07f48d472..00000000000 --- a/package/motion/prefer-omx-encoder.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 71685a1..07ce41c 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -485,7 +485,13 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ - char errstr[128]; - int chkrate; - -- ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); -+ ffmpeg->codec = NULL; -+ if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_H264) -+ ffmpeg->codec = avcodec_find_encoder_by_name("h264_omx"); -+ else if (ffmpeg->oc->oformat->video_codec == AV_CODEC_ID_MPEG4) -+ ffmpeg->codec = avcodec_find_encoder_by_name("mpeg4_omx"); -+ if (!ffmpeg->codec) -+ ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); - if (!ffmpeg->codec) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Codec %s not found", ffmpeg->codec_name); - ffmpeg_free_context(ffmpeg); diff --git a/package/motion/preferred-encoder.patch b/package/motion/preferred-encoder.patch new file mode 100644 index 00000000000..2781da99086 --- /dev/null +++ b/package/motion/preferred-encoder.patch @@ -0,0 +1,145 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 87b4f75..3e7787c 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -236,10 +236,21 @@ static void ffmpeg_free_context(struct ffmpeg *ffmpeg){ + + static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + ++ size_t codec_name_len = strcspn(ffmpeg->codec_name, ":"); ++ char *codec_name = alloca(codec_name_len + 1); ++ ++ if (codec_name == NULL) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Failed to allocate memory for codec name"); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ memcpy(codec_name, ffmpeg->codec_name, codec_name_len); ++ codec_name[codec_name_len] = 0; ++ + /* Only the newer codec and containers can handle the really fast FPS */ +- if (((strcmp(ffmpeg->codec_name, "msmpeg4") == 0) || +- (strcmp(ffmpeg->codec_name, "mpeg4") == 0) || +- (strcmp(ffmpeg->codec_name, "swf") == 0) ) && (ffmpeg->fps >50)){ ++ if (((strcmp(codec_name, "msmpeg4") == 0) || ++ (strcmp(codec_name, "mpeg4") == 0) || ++ (strcmp(codec_name, "swf") == 0) ) && (ffmpeg->fps >50)){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "The frame rate specified is too high for the ffmpeg movie type specified. Choose a different ffmpeg container or lower framerate."); + ffmpeg_free_context(ffmpeg); + return -1; +@@ -250,59 +261,59 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_MPEG2VIDEO; + strncat(ffmpeg->filename, ".mpg", 4); + if (!ffmpeg->oc->oformat) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "ffmpeg_video_codec option value %s is not supported", ffmpeg->codec_name); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "ffmpeg_video_codec option value %s is not supported", codec_name); + ffmpeg_free_context(ffmpeg); + return -1; + } + return 0; + } + +- if (strcmp(ffmpeg->codec_name, "mpeg4") == 0) { ++ if (strcmp(codec_name, "mpeg4") == 0) { + ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); + strncat(ffmpeg->filename, ".avi", 4); + } + +- if (strcmp(ffmpeg->codec_name, "msmpeg4") == 0) { ++ if (strcmp(codec_name, "msmpeg4") == 0) { + ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); + strncat(ffmpeg->filename, ".avi", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_MSMPEG4V2; + } + +- if (strcmp(ffmpeg->codec_name, "swf") == 0) { ++ if (strcmp(codec_name, "swf") == 0) { + ffmpeg->oc->oformat = av_guess_format("swf", NULL, NULL); + strncat(ffmpeg->filename, ".swf", 4); + } + +- if (strcmp(ffmpeg->codec_name, "flv") == 0) { ++ if (strcmp(codec_name, "flv") == 0) { + ffmpeg->oc->oformat = av_guess_format("flv", NULL, NULL); + strncat(ffmpeg->filename, ".flv", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_FLV1; + } + +- if (strcmp(ffmpeg->codec_name, "ffv1") == 0) { ++ if (strcmp(codec_name, "ffv1") == 0) { + ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); + strncat(ffmpeg->filename, ".avi", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_FFV1; + } + +- if (strcmp(ffmpeg->codec_name, "mov") == 0) { ++ if (strcmp(codec_name, "mov") == 0) { + ffmpeg->oc->oformat = av_guess_format("mov", NULL, NULL); + strncat(ffmpeg->filename, ".mov", 4); + } + +- if (strcmp(ffmpeg->codec_name, "mp4") == 0) { ++ if (strcmp(codec_name, "mp4") == 0) { + ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL); + strncat(ffmpeg->filename, ".mp4", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_H264; + } + +- if (strcmp(ffmpeg->codec_name, "mkv") == 0) { ++ if (strcmp(codec_name, "mkv") == 0) { + ffmpeg->oc->oformat = av_guess_format("matroska", NULL, NULL); + strncat(ffmpeg->filename, ".mkv", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_H264; + } + +- if (strcmp(ffmpeg->codec_name, "hevc") == 0) { ++ if (strcmp(codec_name, "hevc") == 0) { + ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL); + strncat(ffmpeg->filename, ".mp4", 4); + if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_HEVC; +@@ -310,7 +321,7 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + + //Check for valid results + if (!ffmpeg->oc->oformat) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "codec option value %s is not supported", ffmpeg->codec_name); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "codec option value %s is not supported", codec_name); + ffmpeg_free_context(ffmpeg); + return -1; + } +@@ -484,13 +495,23 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ + int retcd; + char errstr[128]; + int chkrate; ++ size_t codec_name_len = strcspn(ffmpeg->codec_name, ":"); + +- ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); ++ ffmpeg->codec = NULL; ++ if (ffmpeg->codec_name[codec_name_len]) { ++ ffmpeg->codec = avcodec_find_encoder_by_name(&ffmpeg->codec_name[codec_name_len+1]); ++ if (!ffmpeg->codec) ++ MOTION_LOG(WRN, TYPE_ENCODER, NO_ERRNO, "Preferred codec %s not found", &ffmpeg->codec_name[codec_name_len+1]); ++ } ++ if (!ffmpeg->codec) ++ ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); + if (!ffmpeg->codec) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Codec %s not found", ffmpeg->codec_name); + ffmpeg_free_context(ffmpeg); + return -1; + } ++ if (ffmpeg->codec_name[codec_name_len]) ++ MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO, "Using codec %s", ffmpeg->codec->name); + + #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) + //If we provide the codec to this, it results in a memory leak. ffmpeg ticket: 5714 +diff --git a/ffmpeg.h b/ffmpeg.h +index 78a2785..95383a7 100644 +--- a/ffmpeg.h ++++ b/ffmpeg.h +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include "config.h" + + enum TIMELAPSE_TYPE { From 6a3fc655226ce404764273d4ae78ea820abdd391 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 23 Aug 2017 16:16:10 +1000 Subject: [PATCH 17/17] motioneye: add option to enable hwaccel video encoding --- .../add-hwaccel-video-encoding-option.patch | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 package/motioneye/add-hwaccel-video-encoding-option.patch diff --git a/package/motioneye/add-hwaccel-video-encoding-option.patch b/package/motioneye/add-hwaccel-video-encoding-option.patch new file mode 100644 index 00000000000..6d87327b357 --- /dev/null +++ b/package/motioneye/add-hwaccel-video-encoding-option.patch @@ -0,0 +1,183 @@ +commit 508d177f9f62a33f1062443243d8c1b9c6172edf +Author: Joo Aun Saw +Date: Wed Aug 23 16:12:47 2017 +1000 + + Add option to enable hardware accelerated video encoding + +diff --git a/motioneye/config.py b/motioneye/config.py +index 48e8cf5..b810588 100644 +--- a/motioneye/config.py ++++ b/motioneye/config.py +@@ -57,6 +57,7 @@ _EXPONENTIAL_QUALITY_CODECS = ['mpeg4', 'msmpeg4', 'swf', 'flv', 'mov', 'mkv'] + _EXPONENTIAL_QUALITY_FACTOR = 100000 # voodoo + _EXPONENTIAL_DEF_QUALITY = 511 # about 75% + _MAX_FFMPEG_VARIABLE_BITRATE = 32767 ++_HW_ACCEL_CODECS = ['mp4', 'mkv'] + + _KNOWN_MOTION_OPTIONS = set([ + 'auto_brightness', +@@ -737,6 +738,7 @@ def motion_camera_ui_to_dict(ui, old_config=None): + 'movie_filename': ui['movie_file_name'], + 'max_movie_time': ui['max_movie_length'], + '@preserve_movies': int(ui['preserve_movies']), ++ '@movie_hwaccel': ui['movie_hwaccel'], + + # motion detection + '@motion_detection': ui['motion_detection'], +@@ -930,6 +932,9 @@ def motion_camera_ui_to_dict(ui, old_config=None): + + else: + vbr = max(1, q) ++ if motionctl.has_hwaccel_movie_encoding_support() and ui['movie_hwaccel']: ++ if data['ffmpeg_video_codec'] in _HW_ACCEL_CODECS: ++ data['ffmpeg_video_codec'] = data['ffmpeg_video_codec']+':h264_omx' + + data['ffmpeg_variable_bitrate'] = int(vbr) + +@@ -1120,6 +1125,7 @@ def motion_camera_dict_to_ui(data): + 'movie_file_name': data['movie_filename'], + 'max_movie_length': data['max_movie_time'], + 'preserve_movies': data['@preserve_movies'], ++ 'movie_hwaccel': data['@movie_hwaccel'], + + # motion detection + 'motion_detection': data['@motion_detection'], +@@ -1313,6 +1319,7 @@ def motion_camera_dict_to_ui(data): + ui['recording_mode'] = 'motion-triggered' + + ui['movie_format'] = data['ffmpeg_video_codec'] ++ ui['movie_format'] = [x.strip() for x in ui['movie_format'].split(':')][0] + + bitrate = data['ffmpeg_variable_bitrate'] + if motionctl.needs_ffvb_quirks(): +@@ -1897,6 +1904,7 @@ def _set_default_motion_camera(camera_id, data): + data.setdefault('ffmpeg_variable_bitrate', _EXPONENTIAL_DEF_QUALITY) + + data.setdefault('@preserve_movies', 0) ++ data.setdefault('@movie_hwaccel', 0) + + data.setdefault('@working_schedule', '') + data.setdefault('@working_schedule_type', 'outside') +diff --git a/motioneye/handlers.py b/motioneye/handlers.py +index 051621c..4044d73 100644 +--- a/motioneye/handlers.py ++++ b/motioneye/handlers.py +@@ -221,6 +221,7 @@ class MainHandler(BaseHandler): + admin_username=config.get_main().get('@admin_username'), + has_streaming_auth=motionctl.has_streaming_auth(), + has_new_movie_format_support=motionctl.has_new_movie_format_support(), ++ has_hwaccel_movie_encoding_support=motionctl.has_hwaccel_movie_encoding_support(), + has_motion=bool(motionctl.find_motion()[0]), + mask_width=utils.MASK_WIDTH) + +diff --git a/motioneye/motionctl.py b/motioneye/motionctl.py +index 832ed38..da61c23 100644 +--- a/motioneye/motionctl.py ++++ b/motioneye/motionctl.py +@@ -38,6 +38,7 @@ _LAST_OLD_CONFIG_VERSIONS = (490, '3.2.12') + _started = False + _motion_binary_cache = None + _motion_detected = {} ++_hwaccel_codec_cache = None + + + def find_motion(): +@@ -75,6 +76,38 @@ def find_motion(): + return _motion_binary_cache + + ++def hwaccel_codec_supported(): ++ global _hwaccel_codec_cache ++ if _hwaccel_codec_cache: ++ return _hwaccel_codec_cache ++ ++ if settings.FFMPEG_BINARY: ++ if os.path.exists(settings.FFMPEG_BINARY): ++ binary = settings.FFMPEG_BINARY ++ else: ++ return False ++ ++ else: # autodetect ffmpeg binary path ++ try: ++ binary = subprocess.check_output(['which', 'ffmpeg'], stderr=utils.DEV_NULL).strip() ++ except subprocess.CalledProcessError: # not found ++ return False ++ ++ try: ++ help = subprocess.check_output(binary + ' -codecs -hide_banner', shell=True) ++ ++ except subprocess.CalledProcessError: # not found ++ return False ++ ++ result = re.findall('h264_omx', help, re.IGNORECASE) ++ if result: ++ logging.debug('Hardware accelerated codec found: %s' % result) ++ _hwaccel_codec_cache = True ++ else: ++ _hwaccel_codec_cache = False ++ return _hwaccel_codec_cache ++ ++ + def start(deferred=False): + import config + import mjpgclient +@@ -354,6 +387,10 @@ def has_new_movie_format_support(): + return version.lower().count('git') or update.compare_versions(version, '3.4') >= 0 + + ++def has_hwaccel_movie_encoding_support(): ++ return hwaccel_codec_supported() ++ ++ + def get_rtsp_support(): + binary, version = find_motion() + if not binary: +diff --git a/motioneye/settings.py b/motioneye/settings.py +index cfd8488..8ba1363 100644 +--- a/motioneye/settings.py ++++ b/motioneye/settings.py +@@ -124,3 +124,6 @@ ADD_REMOVE_CAMERAS = True + + # enable HTTPS certificate validation + VALIDATE_CERTS = True ++ ++# path to the ffmpeg binary (automatically detected by default) ++FFMPEG_BINARY = None +diff --git a/motioneye/static/js/main.js b/motioneye/static/js/main.js +index ac43386..1a25d76 100644 +--- a/motioneye/static/js/main.js ++++ b/motioneye/static/js/main.js +@@ -1869,6 +1869,7 @@ function cameraUi2Dict() { + 'movie_file_name': $('#movieFileNameEntry').val(), + 'movie_quality': $('#movieQualitySlider').val(), + 'movie_format': $('#movieFormatSelect').val(), ++ 'movie_hwaccel': $('#hwaccelEncoding')[0].checked, + 'recording_mode': $('#recordingModeSelect').val(), + 'max_movie_length': $('#maxMovieLengthEntry').val(), + 'preserve_movies': $('#preserveMoviesSelect').val() >= 0 ? $('#preserveMoviesSelect').val() : $('#moviesLifetimeEntry').val(), +@@ -2219,6 +2220,7 @@ function dict2CameraUi(dict) { + $('#movieFileNameEntry').val(dict['movie_file_name']); markHideIfNull('movie_file_name', 'movieFileNameEntry'); + $('#movieQualitySlider').val(dict['movie_quality']); markHideIfNull('movie_quality', 'movieQualitySlider'); + $('#movieFormatSelect').val(dict['movie_format']); markHideIfNull('movie_format', 'movieFormatSelect'); ++ $('#hwaccelEncoding')[0].checked = dict['movie_hwaccel']; markHideIfNull('movie_hwaccel', 'hwaccelEncoding'); + $('#recordingModeSelect').val(dict['recording_mode']); markHideIfNull('recording_mode', 'recordingModeSelect'); + $('#maxMovieLengthEntry').val(dict['max_movie_length']); markHideIfNull('max_movie_length', 'maxMovieLengthEntry'); + $('#preserveMoviesSelect').val(dict['preserve_movies']); +diff --git a/motioneye/templates/main.html b/motioneye/templates/main.html +index e2b38d8..3fc6183 100644 +--- a/motioneye/templates/main.html ++++ b/motioneye/templates/main.html +@@ -762,6 +762,13 @@ + + ? + ++ {% if has_hwaccel_movie_encoding_support %} ++ ++ Hardware Acceleration ++ ++ ? ++ ++ {% endif %} + + Recording Mode +