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/28] 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 0000000000..2e9ebb527e --- /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 0000000000..2e9ebb527e --- /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 0000000000..2e9ebb527e --- /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 bbf9509333..7d17de0d7a 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 b5850db722..187432d49a 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 6540d41c52..d9c140d965 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 0000000000..73d41b63d5 --- /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 0000000000..d41b32ce59 --- /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/28] 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 73d41b63d5..0000000000 --- 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 d41b32ce59..0000000000 --- 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 f3815e37a4..70ffcf7c31 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/28] 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 0000000000..b3f778e950 --- /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/28] 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 0000000000..29d561b3d9 --- /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/28] 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 871aa5ec8c..3b6c7fe1ef 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 9a68f6f1b0..7aa8e089a9 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/28] 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 6adf7e440a..77e185f5ed 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 d9c140d965..4bdd9e6f50 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/28] 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 70ffcf7c31..f783053cef 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/28] 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 f783053cef..b8f6004813 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/28] 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 b3f778e950..0000000000 --- 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 29d561b3d9..0000000000 --- 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 0000000000..f77bff853a --- /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/28] 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 f77bff853a..0000000000 --- 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 0000000000..129ae75677 --- /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/28] 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 401a69f322..43bd68d658 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/28] 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 0000000000..06637cc1d6 --- /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/28] 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 0000000000..6733d8bafc --- /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 0000000000..ac07f48d47 --- /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 0000000000..0f78b6fc78 --- /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 129ae75677..0000000000 --- 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/28] 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 0f78b6fc78..994754f022 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/28] 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 b8f6004813..46479cf572 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/28] 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 ac07f48d47..0000000000 --- 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 0000000000..2781da9908 --- /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/28] 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 0000000000..6d87327b35 --- /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 + From a009f8467648ed5a5b6e948f8fa48b2f556ebeee Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 27 Aug 2017 17:16:09 +0300 Subject: [PATCH 18/28] update motioneye --- package/motioneye/motioneye.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/motioneye/motioneye.mk b/package/motioneye/motioneye.mk index 158ecdc054..e146f4e6b6 100644 --- a/package/motioneye/motioneye.mk +++ b/package/motioneye/motioneye.mk @@ -4,7 +4,7 @@ # ############################################################# -MOTIONEYE_VERSION = 9d546ec1aa8da1fe27ad5c0ad212bdb2baf8dce1 +MOTIONEYE_VERSION = 1744cfaffc7ef9800226f5ee86270cd7ee31277d MOTIONEYE_SITE = $(call github,ccrisan,motioneye,$(MOTIONEYE_VERSION)) MOTIONEYE_SOURCE = $(MOTIONEYE_VERSION).tar.gz MOTIONEYE_LICENSE = GPLv3 From c3969e4c002e0b35456627278d6de532b00e79f0 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sun, 27 Aug 2017 17:21:42 +0300 Subject: [PATCH 19/28] Delete add-hwaccel-video-encoding-option.patch --- .../add-hwaccel-video-encoding-option.patch | 183 ------------------ 1 file changed, 183 deletions(-) delete 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 deleted file mode 100644 index 6d87327b35..0000000000 --- a/package/motioneye/add-hwaccel-video-encoding-option.patch +++ /dev/null @@ -1,183 +0,0 @@ -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 - From 6ed28eb2d62688b0419b83ec5a23361c34f04321 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Mon, 28 Aug 2017 17:52:02 +0300 Subject: [PATCH 20/28] update motion; remove obsolete patch --- package/motion/motion.mk | 2 +- .../temp-fix-for-extpipe-subdir-creation.patch | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 package/motion/temp-fix-for-extpipe-subdir-creation.patch diff --git a/package/motion/motion.mk b/package/motion/motion.mk index 46479cf572..c21abf4248 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -4,7 +4,7 @@ # ################################################################################ -MOTION_VERSION = ab9e800d5984f2907f00bebabc794d1dba9682ad +MOTION_VERSION = d23e263490a54329329b64883f1860ada5e5920b 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 \ diff --git a/package/motion/temp-fix-for-extpipe-subdir-creation.patch b/package/motion/temp-fix-for-extpipe-subdir-creation.patch deleted file mode 100644 index 06637cc1d6..0000000000 --- a/package/motion/temp-fix-for-extpipe-subdir-creation.patch +++ /dev/null @@ -1,17 +0,0 @@ -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 bb25e40387e54ba7430951b9963db54017d8f37c Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Mon, 28 Aug 2017 20:31:21 +0300 Subject: [PATCH 21/28] update motione (h264_omx support is now properly detected) --- package/motioneye/motioneye.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/motioneye/motioneye.mk b/package/motioneye/motioneye.mk index e146f4e6b6..6812b9c216 100644 --- a/package/motioneye/motioneye.mk +++ b/package/motioneye/motioneye.mk @@ -4,7 +4,7 @@ # ############################################################# -MOTIONEYE_VERSION = 1744cfaffc7ef9800226f5ee86270cd7ee31277d +MOTIONEYE_VERSION = a6601e3a2fd714284a1e10b3b330f9230d93a17d MOTIONEYE_SITE = $(call github,ccrisan,motioneye,$(MOTIONEYE_VERSION)) MOTIONEYE_SOURCE = $(MOTIONEYE_VERSION).tar.gz MOTIONEYE_LICENSE = GPLv3 From 624bb7e30a70e49ef67b44ce6171f230dc50957e Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 30 Aug 2017 13:00:55 +1000 Subject: [PATCH 22/28] motion: reworked movie encode quality --- package/motion/tune-h264-encode-quality.patch | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch index 994754f022..c989af5ccf 100644 --- a/package/motion/tune-h264-encode-quality.patch +++ b/package/motion/tune-h264-encode-quality.patch @@ -1,42 +1,53 @@ diff --git a/ffmpeg.c b/ffmpeg.c -index a4d3757..368c855 100644 +index 87b4f75..4816adf 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -451,7 +451,7 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +@@ -451,21 +451,30 @@ 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; -@@ -459,13 +459,24 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ + if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ - if (ffmpeg->vbr > 0) { - 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; +- if (ffmpeg->vbr > 0) { +- ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); ++ if (ffmpeg->vbr <= 0) ++ ffmpeg->vbr = 45; // default to 45% quality ++ av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); ++ av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); ++ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0)) { ++ // H264 OMX encoder quality can only be controlled via bit_rate ++ // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ++ ffmpeg->vbr = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 7; ++ // Clip bit rate to min ++ if (ffmpeg->vbr < 4000) // magic number ++ ffmpeg->vbr = 4000; ++ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; ++ ffmpeg->ctx_codec->bit_rate = ffmpeg->vbr; } else { -+ bit_rate = ffmpeg->bps; - ffmpeg->vbr = 28; +- ffmpeg->vbr = 28; ++ // Control other H264 encoders quality via CRF ++ char crf[4]; ++ ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); ++ snprintf(crf, 4, "%d", ffmpeg->vbr); ++ av_dict_set(&ffmpeg->opts, "crf", crf, 0); } - 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); -+ 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); -+ 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){ +@@ -474,7 +483,7 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ + ffmpeg->ctx_codec->global_quality=ffmpeg->vbr; + } + } +- MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "vbr/crf for codec: %d", ffmpeg->vbr); ++ MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "%s codec vbr/crf/bit_rate: %d", ffmpeg->codec->name, ffmpeg->vbr); + + return 0; + } From ea56807852fa99526555f7a7e087afeaef5b5259 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 5 Sep 2017 14:52:24 +1000 Subject: [PATCH 23/28] motion: drain codec at end of recording --- .../motion/0010-set-pts-before-encode.patch | 76 ++++++++ .../0011-decouple-avcodec-send-receive.patch | 176 ++++++++++++++++++ package/motion/0012-drain-codec.patch | 68 +++++++ 3 files changed, 320 insertions(+) create mode 100644 package/motion/0010-set-pts-before-encode.patch create mode 100644 package/motion/0011-decouple-avcodec-send-receive.patch create mode 100644 package/motion/0012-drain-codec.patch diff --git a/package/motion/0010-set-pts-before-encode.patch b/package/motion/0010-set-pts-before-encode.patch new file mode 100644 index 0000000000..87ca85a7bb --- /dev/null +++ b/package/motion/0010-set-pts-before-encode.patch @@ -0,0 +1,76 @@ +commit 2c072634efd8e3b7fb70a1d85cd54e9befe96dd2 +Author: Joo Aun Saw +Date: Tue Sep 5 11:09:41 2017 +1000 + + set PTS value before encoding + +diff --git a/ffmpeg.c b/ffmpeg.c +index 87b4f75..739bcb3 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -419,8 +419,7 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + + if (ffmpeg->tlapse != TIMELAPSE_NONE) { + ffmpeg->last_pts++; +- ffmpeg->pkt.pts = ffmpeg->last_pts; +- ffmpeg->pkt.dts = ffmpeg->last_pts; ++ ffmpeg->picture->pts = ffmpeg->last_pts; + } else { + pts_interval = ((1000000L * (tv1->tv_sec - ffmpeg->start_time.tv_sec)) + tv1->tv_usec - ffmpeg->start_time.tv_usec); + if (pts_interval < 0){ +@@ -428,23 +427,22 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg_reset_movie_start_time(ffmpeg, tv1); + pts_interval = 0; + } +- ffmpeg->pkt.pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; ++ ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; + + if (ffmpeg->test_mode == 1){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "PTS %"PRId64" Base PTS %"PRId64" ms interval %"PRId64" timebase %d-%d", +- ffmpeg->pkt.pts,ffmpeg->base_pts,pts_interval, ++ ffmpeg->picture->pts,ffmpeg->base_pts,pts_interval, + ffmpeg->video_st->time_base.num,ffmpeg->video_st->time_base.den); + } + +- if (ffmpeg->pkt.pts <= ffmpeg->last_pts){ ++ if (ffmpeg->picture->pts <= ffmpeg->last_pts){ + //We have a problem with our motion loop timing and sending frames or the rounding into the PTS. + if (ffmpeg->test_mode == 1){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "BAD TIMING!! Frame skipped."); + } + return -1; + } +- ffmpeg->pkt.dts = ffmpeg->pkt.pts; +- ffmpeg->last_pts = ffmpeg->pkt.pts; ++ ffmpeg->last_pts = ffmpeg->picture->pts; + } + return 0; + } +@@ -703,13 +701,6 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg->pkt.data = NULL; + ffmpeg->pkt.size = 0; + +- retcd = ffmpeg_encode_video(ffmpeg); +- if (retcd != 0){ +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); +- my_packet_unref(ffmpeg->pkt); +- return retcd; +- } +- + retcd = ffmpeg_set_pts(ffmpeg, tv1); + if (retcd < 0) { + //If there is an error, it has already been reported. +@@ -717,6 +708,13 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + return -1; + } + ++ retcd = ffmpeg_encode_video(ffmpeg); ++ if (retcd != 0){ ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); ++ my_packet_unref(ffmpeg->pkt); ++ return retcd; ++ } ++ + if (ffmpeg->tlapse == TIMELAPSE_APPEND) { + retcd = ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); + } else { diff --git a/package/motion/0011-decouple-avcodec-send-receive.patch b/package/motion/0011-decouple-avcodec-send-receive.patch new file mode 100644 index 0000000000..48becbe9e5 --- /dev/null +++ b/package/motion/0011-decouple-avcodec-send-receive.patch @@ -0,0 +1,176 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 739bcb3..0e44c97 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -324,6 +324,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + return 0; + } + ++static int ffmpeg_write_packet(struct ffmpeg *ffmpeg){ ++ ++ if (ffmpeg->tlapse == TIMELAPSE_APPEND) { ++ return ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); ++ } else { ++ return av_write_frame(ffmpeg->oc, &ffmpeg->pkt); ++ } ++} ++ + static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) +@@ -331,27 +340,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + int retcd = 0; + char errstr[128]; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + retcd = avcodec_send_frame(ffmpeg->ctx_codec, ffmpeg->picture); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error sending frame for encoding:%s",errstr); +- return -1; +- } +- retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); +- if (retcd == AVERROR(EAGAIN)){ +- //Buffered packet. Throw special return code + my_packet_unref(ffmpeg->pkt); +- return -2; +- } +- if (retcd < 0 ){ +- av_strerror(retcd, errstr, sizeof(errstr)); +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error receiving encoded packet video:%s",errstr); +- //Packet is freed upon failure of encoding + return -1; + } +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; ++ while (retcd >= 0) { ++ retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); ++ if (retcd == AVERROR(EAGAIN)){ ++ //Buffered packet. Throw special return code ++ my_packet_unref(ffmpeg->pkt); ++ return -2; ++ } ++ if (retcd < 0 ){ ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error receiving encoded packet video:%s",errstr); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } else { ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ } ++ } + ++ my_packet_unref(ffmpeg->pkt); + return 0; + + #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) +@@ -360,11 +383,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + char errstr[128]; + int got_packet_ptr; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, ffmpeg->picture, &got_packet_ptr); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error encoding video:%s",errstr); +- //Packet is freed upon failure of encoding ++ my_packet_unref(ffmpeg->pkt); + return -1; + } + if (got_packet_ptr == 0){ +@@ -376,6 +403,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + if (ffmpeg->picture->key_frame == 1) + ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; + ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ ++ my_packet_unref(ffmpeg->pkt); + return 0; + + #else +@@ -384,6 +420,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + uint8_t *video_outbuf; + int video_outbuf_size; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; + video_outbuf = mymalloc(video_outbuf_size); + +@@ -407,6 +447,16 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + free(video_outbuf); + ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ ++ my_packet_unref(ffmpeg->pkt); + return 0; + + #endif +@@ -697,36 +747,18 @@ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ + static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + int retcd; + +- av_init_packet(&ffmpeg->pkt); +- ffmpeg->pkt.data = NULL; +- ffmpeg->pkt.size = 0; +- + retcd = ffmpeg_set_pts(ffmpeg, tv1); + if (retcd < 0) { + //If there is an error, it has already been reported. +- my_packet_unref(ffmpeg->pkt); + return -1; + } + + retcd = ffmpeg_encode_video(ffmpeg); +- if (retcd != 0){ +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); +- my_packet_unref(ffmpeg->pkt); +- return retcd; +- } +- +- if (ffmpeg->tlapse == TIMELAPSE_APPEND) { +- retcd = ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); +- } else { +- retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); ++ if (retcd < 0){ ++ if (retcd != -2) ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); + } +- my_packet_unref(ffmpeg->pkt); + +- if (retcd < 0) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); +- ffmpeg_free_context(ffmpeg); +- return -1; +- } + return retcd; + + } diff --git a/package/motion/0012-drain-codec.patch b/package/motion/0012-drain-codec.patch new file mode 100644 index 0000000000..3350e6a16d --- /dev/null +++ b/package/motion/0012-drain-codec.patch @@ -0,0 +1,68 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 0e44c97..e5a2b9e 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -463,6 +463,55 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + } + ++static int ffmpeg_drain_codec(struct ffmpeg *ffmpeg){ ++ ++#if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) ++ //ffmpeg version 3.1 and after ++ int retcd = 0; ++ char errstr[128]; ++ ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ ++ retcd = avcodec_send_frame(ffmpeg->ctx_codec, NULL); ++ if (retcd < 0 ){ ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error draining codec:%s",errstr); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } ++ for (;;) { ++ retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); ++ if (retcd == AVERROR_EOF) ++ break; ++ if (retcd < 0 ){ ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error receiving encoded packet video:%s",errstr); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } else { ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } ++ } ++ } ++ ++ my_packet_unref(ffmpeg->pkt); ++ return 0; ++ ++#else ++ ++ // do nothing ++ return 0; ++ ++#endif ++ ++} ++ + static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + + int64_t pts_interval; +@@ -894,6 +943,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ + #ifdef HAVE_FFMPEG + + if (ffmpeg != NULL) { ++ ffmpeg_drain_codec(ffmpeg); + if (ffmpeg->tlapse != TIMELAPSE_APPEND) { + av_write_trailer(ffmpeg->oc); + } From 3dc0ef0b2f3df202028522018599fa771c3004ce Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 5 Sep 2017 14:55:19 +1000 Subject: [PATCH 24/28] motion: replace alloca with malloc --- package/motion/preferred-encoder.patch | 42 +++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/package/motion/preferred-encoder.patch b/package/motion/preferred-encoder.patch index 2781da9908..4b6471c303 100644 --- a/package/motion/preferred-encoder.patch +++ b/package/motion/preferred-encoder.patch @@ -1,13 +1,13 @@ diff --git a/ffmpeg.c b/ffmpeg.c -index 87b4f75..3e7787c 100644 +index 87b4f75..f3c685a 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -236,10 +236,21 @@ static void ffmpeg_free_context(struct ffmpeg *ffmpeg){ +@@ -236,12 +236,24 @@ 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); ++ char *codec_name = malloc(codec_name_len + 1); + + if (codec_name == NULL) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Failed to allocate memory for codec name"); @@ -26,16 +26,21 @@ index 87b4f75..3e7787c 100644 + (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); ++ free(codec_name); return -1; -@@ -250,59 +261,59 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + } + +@@ -250,59 +262,61 @@ 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); ++ free(codec_name); return -1; } ++ free(codec_name); return 0; } @@ -97,16 +102,29 @@ index 87b4f75..3e7787c 100644 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){ +@@ -310,17 +324,20 @@ 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); ++ free(codec_name); return -1; } -@@ -484,13 +495,23 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ + + if (ffmpeg->oc->oformat->video_codec == MY_CODEC_ID_NONE) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Could not get the codec"); + ffmpeg_free_context(ffmpeg); ++ free(codec_name); + return -1; + } + ++ free(codec_name); + return 0; + } + +@@ -484,13 +501,23 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ int retcd; char errstr[128]; int chkrate; @@ -131,15 +149,3 @@ index 87b4f75..3e7787c 100644 #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 bd36e6edc48d3b78ac4653e9035ba59ae771a673 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 12 Sep 2017 16:19:26 +1000 Subject: [PATCH 25/28] motion: split patches into smaller chunks --- .../motion/0011-do-not-force-keyframe.patch | 39 +++++++++++++++++++ ... 0012-decouple-avcodec-send-receive.patch} | 35 ++++++++++------- ...ain-codec.patch => 0013-drain-codec.patch} | 0 3 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 package/motion/0011-do-not-force-keyframe.patch rename package/motion/{0011-decouple-avcodec-send-receive.patch => 0012-decouple-avcodec-send-receive.patch} (87%) rename package/motion/{0012-drain-codec.patch => 0013-drain-codec.patch} (100%) diff --git a/package/motion/0011-do-not-force-keyframe.patch b/package/motion/0011-do-not-force-keyframe.patch new file mode 100644 index 0000000000..82a5d65155 --- /dev/null +++ b/package/motion/0011-do-not-force-keyframe.patch @@ -0,0 +1,39 @@ +commit 52b6beab2975ec609c7a072b1ed037a84ea92c14 +Author: Joo Aun Saw +Date: Tue Sep 12 15:29:28 2017 +1000 + + do not force packet keyframe + +diff --git a/ffmpeg.c b/ffmpeg.c +index 739bcb3..dac1d6d 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -349,8 +349,6 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + //Packet is freed upon failure of encoding + return -1; + } +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; + + return 0; + +@@ -373,9 +371,6 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -2; + } + +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; +- + return 0; + + #else +@@ -402,9 +397,6 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.size = retcd; + ffmpeg->pkt.data = video_outbuf; + +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; +- + free(video_outbuf); + + return 0; diff --git a/package/motion/0011-decouple-avcodec-send-receive.patch b/package/motion/0012-decouple-avcodec-send-receive.patch similarity index 87% rename from package/motion/0011-decouple-avcodec-send-receive.patch rename to package/motion/0012-decouple-avcodec-send-receive.patch index 48becbe9e5..6ef008db16 100644 --- a/package/motion/0011-decouple-avcodec-send-receive.patch +++ b/package/motion/0012-decouple-avcodec-send-receive.patch @@ -1,5 +1,11 @@ +commit e9e7cf1bc641202d8babe09204857ffff8e497c5 +Author: Joo Aun Saw +Date: Tue Sep 12 16:04:09 2017 +1000 + + decouple avcodec send receive + diff --git a/ffmpeg.c b/ffmpeg.c -index 739bcb3..0e44c97 100644 +index dac1d6d..6cd48fa 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -324,6 +324,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ @@ -18,7 +24,7 @@ index 739bcb3..0e44c97 100644 static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) -@@ -331,27 +340,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -331,25 +340,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ int retcd = 0; char errstr[128]; @@ -44,8 +50,6 @@ index 739bcb3..0e44c97 100644 - //Packet is freed upon failure of encoding return -1; } -- if (ffmpeg->picture->key_frame == 1) -- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; + while (retcd >= 0) { + retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); + if (retcd == AVERROR(EAGAIN)){ @@ -73,7 +77,7 @@ index 739bcb3..0e44c97 100644 return 0; #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) -@@ -360,11 +383,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -358,11 +383,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ char errstr[128]; int got_packet_ptr; @@ -90,9 +94,9 @@ index 739bcb3..0e44c97 100644 return -1; } if (got_packet_ptr == 0){ -@@ -376,6 +403,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ - if (ffmpeg->picture->key_frame == 1) - ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; +@@ -371,6 +400,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -2; + } + retcd = ffmpeg_write_packet(ffmpeg); + if (retcd < 0) { @@ -106,7 +110,7 @@ index 739bcb3..0e44c97 100644 return 0; #else -@@ -384,6 +420,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -379,6 +417,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ uint8_t *video_outbuf; int video_outbuf_size; @@ -117,24 +121,27 @@ index 739bcb3..0e44c97 100644 video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; video_outbuf = mymalloc(video_outbuf_size); -@@ -407,6 +447,16 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ - - free(video_outbuf); +@@ -397,8 +439,18 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.size = retcd; + ffmpeg->pkt.data = video_outbuf; +- free(video_outbuf); + retcd = ffmpeg_write_packet(ffmpeg); + if (retcd < 0) { + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); ++ free(video_outbuf); + ffmpeg_free_context(ffmpeg); + return -1; + } -+ + + my_packet_unref(ffmpeg->pkt); ++ free(video_outbuf); return 0; #endif -@@ -697,36 +747,18 @@ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ +@@ -689,36 +741,18 @@ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ int retcd; diff --git a/package/motion/0012-drain-codec.patch b/package/motion/0013-drain-codec.patch similarity index 100% rename from package/motion/0012-drain-codec.patch rename to package/motion/0013-drain-codec.patch From 4e045cb1d54a40ffda7f6d45e3b9fcc24fc98b60 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 18 Sep 2017 15:54:06 +1000 Subject: [PATCH 26/28] motion: updated --- 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 c21abf4248..55ca2d14f2 100644 --- a/package/motion/motion.mk +++ b/package/motion/motion.mk @@ -4,7 +4,7 @@ # ################################################################################ -MOTION_VERSION = d23e263490a54329329b64883f1860ada5e5920b +MOTION_VERSION = 2a140fa31feafd960033ad292615a601a1f3faec 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 5e743f3477259cf24c35520e7e980418bce3568b Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 18 Sep 2017 16:14:42 +1000 Subject: [PATCH 27/28] motion: updated patches to match motion version --- .../motion/0010-set-pts-before-encode.patch | 76 --------- .../motion/0011-do-not-force-keyframe.patch | 23 +-- .../0012-decouple-avcodec-send-receive.patch | 39 +++-- package/motion/0013-drain-codec.patch | 145 ++++++++++------- package/motion/enable-h264-omx-codec.patch | 13 ++ package/motion/preferred-encoder.patch | 151 ------------------ package/motion/tune-h264-encode-quality.patch | 53 ------ 7 files changed, 133 insertions(+), 367 deletions(-) delete mode 100644 package/motion/0010-set-pts-before-encode.patch create mode 100644 package/motion/enable-h264-omx-codec.patch delete mode 100644 package/motion/preferred-encoder.patch delete mode 100644 package/motion/tune-h264-encode-quality.patch diff --git a/package/motion/0010-set-pts-before-encode.patch b/package/motion/0010-set-pts-before-encode.patch deleted file mode 100644 index 87ca85a7bb..0000000000 --- a/package/motion/0010-set-pts-before-encode.patch +++ /dev/null @@ -1,76 +0,0 @@ -commit 2c072634efd8e3b7fb70a1d85cd54e9befe96dd2 -Author: Joo Aun Saw -Date: Tue Sep 5 11:09:41 2017 +1000 - - set PTS value before encoding - -diff --git a/ffmpeg.c b/ffmpeg.c -index 87b4f75..739bcb3 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -419,8 +419,7 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - - if (ffmpeg->tlapse != TIMELAPSE_NONE) { - ffmpeg->last_pts++; -- ffmpeg->pkt.pts = ffmpeg->last_pts; -- ffmpeg->pkt.dts = ffmpeg->last_pts; -+ ffmpeg->picture->pts = ffmpeg->last_pts; - } else { - pts_interval = ((1000000L * (tv1->tv_sec - ffmpeg->start_time.tv_sec)) + tv1->tv_usec - ffmpeg->start_time.tv_usec); - if (pts_interval < 0){ -@@ -428,23 +427,22 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - ffmpeg_reset_movie_start_time(ffmpeg, tv1); - pts_interval = 0; - } -- ffmpeg->pkt.pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; -+ ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; - - if (ffmpeg->test_mode == 1){ - MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "PTS %"PRId64" Base PTS %"PRId64" ms interval %"PRId64" timebase %d-%d", -- ffmpeg->pkt.pts,ffmpeg->base_pts,pts_interval, -+ ffmpeg->picture->pts,ffmpeg->base_pts,pts_interval, - ffmpeg->video_st->time_base.num,ffmpeg->video_st->time_base.den); - } - -- if (ffmpeg->pkt.pts <= ffmpeg->last_pts){ -+ if (ffmpeg->picture->pts <= ffmpeg->last_pts){ - //We have a problem with our motion loop timing and sending frames or the rounding into the PTS. - if (ffmpeg->test_mode == 1){ - MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "BAD TIMING!! Frame skipped."); - } - return -1; - } -- ffmpeg->pkt.dts = ffmpeg->pkt.pts; -- ffmpeg->last_pts = ffmpeg->pkt.pts; -+ ffmpeg->last_pts = ffmpeg->picture->pts; - } - return 0; - } -@@ -703,13 +701,6 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - ffmpeg->pkt.data = NULL; - ffmpeg->pkt.size = 0; - -- retcd = ffmpeg_encode_video(ffmpeg); -- if (retcd != 0){ -- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); -- my_packet_unref(ffmpeg->pkt); -- return retcd; -- } -- - retcd = ffmpeg_set_pts(ffmpeg, tv1); - if (retcd < 0) { - //If there is an error, it has already been reported. -@@ -717,6 +708,13 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - return -1; - } - -+ retcd = ffmpeg_encode_video(ffmpeg); -+ if (retcd != 0){ -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); -+ my_packet_unref(ffmpeg->pkt); -+ return retcd; -+ } -+ - if (ffmpeg->tlapse == TIMELAPSE_APPEND) { - retcd = ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); - } else { diff --git a/package/motion/0011-do-not-force-keyframe.patch b/package/motion/0011-do-not-force-keyframe.patch index 82a5d65155..7eb9c1f3a7 100644 --- a/package/motion/0011-do-not-force-keyframe.patch +++ b/package/motion/0011-do-not-force-keyframe.patch @@ -1,11 +1,5 @@ -commit 52b6beab2975ec609c7a072b1ed037a84ea92c14 -Author: Joo Aun Saw -Date: Tue Sep 12 15:29:28 2017 +1000 - - do not force packet keyframe - diff --git a/ffmpeg.c b/ffmpeg.c -index 739bcb3..dac1d6d 100644 +index 739bcb3..aa17ddc 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -349,8 +349,6 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ @@ -27,13 +21,20 @@ index 739bcb3..dac1d6d 100644 return 0; #else -@@ -402,9 +397,6 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -399,12 +394,16 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -2; + } + ++ // Encoder did not provide metadata, set it up manually ffmpeg->pkt.size = retcd; ffmpeg->pkt.data = video_outbuf; -- if (ffmpeg->picture->key_frame == 1) -- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; -- + if (ffmpeg->picture->key_frame == 1) + ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; + ++ ffmpeg->pkt.pts = ffmpeg->picture->pts; ++ ffmpeg->pkt.dts = ffmpeg->pkt.pts; ++ free(video_outbuf); return 0; diff --git a/package/motion/0012-decouple-avcodec-send-receive.patch b/package/motion/0012-decouple-avcodec-send-receive.patch index 6ef008db16..562e358788 100644 --- a/package/motion/0012-decouple-avcodec-send-receive.patch +++ b/package/motion/0012-decouple-avcodec-send-receive.patch @@ -1,14 +1,14 @@ -commit e9e7cf1bc641202d8babe09204857ffff8e497c5 +commit 2220065f0e2240e963aeb9bc99fd7c233ea2834d Author: Joo Aun Saw -Date: Tue Sep 12 16:04:09 2017 +1000 +Date: Mon Sep 18 14:21:36 2017 +1000 decouple avcodec send receive diff --git a/ffmpeg.c b/ffmpeg.c -index dac1d6d..6cd48fa 100644 +index 560e7d4..aa06bef 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -324,6 +324,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ +@@ -341,6 +341,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ return 0; } @@ -24,7 +24,7 @@ index dac1d6d..6cd48fa 100644 static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) -@@ -331,25 +340,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -348,25 +357,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ int retcd = 0; char errstr[128]; @@ -77,7 +77,7 @@ index dac1d6d..6cd48fa 100644 return 0; #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) -@@ -358,11 +383,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -375,11 +400,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ char errstr[128]; int got_packet_ptr; @@ -94,7 +94,7 @@ index dac1d6d..6cd48fa 100644 return -1; } if (got_packet_ptr == 0){ -@@ -371,6 +400,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -388,6 +417,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ return -2; } @@ -110,7 +110,7 @@ index dac1d6d..6cd48fa 100644 return 0; #else -@@ -379,6 +417,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -396,6 +434,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ uint8_t *video_outbuf; int video_outbuf_size; @@ -121,9 +121,9 @@ index dac1d6d..6cd48fa 100644 video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; video_outbuf = mymalloc(video_outbuf_size); -@@ -397,8 +439,18 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ - ffmpeg->pkt.size = retcd; - ffmpeg->pkt.data = video_outbuf; +@@ -421,8 +463,18 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.pts = ffmpeg->picture->pts; + ffmpeg->pkt.dts = ffmpeg->pkt.pts; - free(video_outbuf); + retcd = ffmpeg_write_packet(ffmpeg); @@ -141,7 +141,7 @@ index dac1d6d..6cd48fa 100644 return 0; #endif -@@ -689,36 +741,18 @@ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ +@@ -759,35 +811,16 @@ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ int retcd; @@ -153,7 +153,7 @@ index dac1d6d..6cd48fa 100644 if (retcd < 0) { //If there is an error, it has already been reported. - my_packet_unref(ffmpeg->pkt); - return -1; + return 0; } retcd = ffmpeg_encode_video(ffmpeg); @@ -167,17 +167,16 @@ index dac1d6d..6cd48fa 100644 - retcd = ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); - } else { - retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); -+ if (retcd < 0){ -+ if (retcd != -2) -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); - } +- } - my_packet_unref(ffmpeg->pkt); - +- - if (retcd < 0) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); - ffmpeg_free_context(ffmpeg); - return -1; -- } ++ if (retcd < 0){ ++ if (retcd != -2) ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); + } return retcd; - } diff --git a/package/motion/0013-drain-codec.patch b/package/motion/0013-drain-codec.patch index 3350e6a16d..e9c17357cb 100644 --- a/package/motion/0013-drain-codec.patch +++ b/package/motion/0013-drain-codec.patch @@ -1,68 +1,101 @@ +commit 9c604dc427804b9620044a2bdddca1b8c1831627 +Author: Joo Aun Saw +Date: Mon Sep 18 14:30:22 2017 +1000 + + drain codec at end of recording + diff --git a/ffmpeg.c b/ffmpeg.c -index 0e44c97..e5a2b9e 100644 +index aa06bef..c690896 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -463,6 +463,55 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ - +@@ -350,7 +350,7 @@ static int ffmpeg_write_packet(struct ffmpeg *ffmpeg){ + } } -+static int ffmpeg_drain_codec(struct ffmpeg *ffmpeg){ -+ -+#if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) -+ //ffmpeg version 3.1 and after -+ int retcd = 0; -+ char errstr[128]; -+ -+ av_init_packet(&ffmpeg->pkt); -+ ffmpeg->pkt.data = NULL; -+ ffmpeg->pkt.size = 0; -+ -+ retcd = avcodec_send_frame(ffmpeg->ctx_codec, NULL); -+ if (retcd < 0 ){ -+ av_strerror(retcd, errstr, sizeof(errstr)); -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error draining codec:%s",errstr); -+ my_packet_unref(ffmpeg->pkt); -+ return -1; -+ } -+ for (;;) { -+ retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); -+ if (retcd == AVERROR_EOF) -+ break; -+ if (retcd < 0 ){ -+ av_strerror(retcd, errstr, sizeof(errstr)); -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error receiving encoded packet video:%s",errstr); -+ my_packet_unref(ffmpeg->pkt); -+ return -1; -+ } else { -+ retcd = ffmpeg_write_packet(ffmpeg); -+ if (retcd < 0) { -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); -+ my_packet_unref(ffmpeg->pkt); -+ return -1; -+ } -+ } -+ } -+ -+ my_packet_unref(ffmpeg->pkt); -+ return 0; -+ -+#else -+ -+ // do nothing -+ return 0; -+ -+#endif -+ -+} -+ - static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +-static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ++static int ffmpeg_encode_video(struct ffmpeg *ffmpeg, AVFrame *picture){ - int64_t pts_interval; -@@ -894,6 +943,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ + #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) + //ffmpeg version 3.1 and after +@@ -361,7 +361,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.data = NULL; + ffmpeg->pkt.size = 0; + +- retcd = avcodec_send_frame(ffmpeg->ctx_codec, ffmpeg->picture); ++ retcd = avcodec_send_frame(ffmpeg->ctx_codec, picture); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error sending frame for encoding:%s",errstr); +@@ -370,10 +370,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + } + while (retcd >= 0) { + retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); +- if (retcd == AVERROR(EAGAIN)){ +- //Buffered packet. Throw special return code +- my_packet_unref(ffmpeg->pkt); +- return -2; ++ if (picture == NULL) { ++ if (retcd == AVERROR_EOF) ++ break; ++ } else { ++ if (retcd == AVERROR(EAGAIN)){ ++ //Buffered packet. Throw special return code ++ my_packet_unref(ffmpeg->pkt); ++ return -2; ++ } + } + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); +@@ -404,7 +409,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.data = NULL; + ffmpeg->pkt.size = 0; + +- retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, ffmpeg->picture, &got_packet_ptr); ++ retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, picture, &got_packet_ptr); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error encoding video:%s",errstr); +@@ -441,7 +446,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; + video_outbuf = mymalloc(video_outbuf_size); + +- retcd = avcodec_encode_video(ffmpeg->video_st->codec, video_outbuf, video_outbuf_size, ffmpeg->picture); ++ retcd = avcodec_encode_video(ffmpeg->video_st->codec, video_outbuf, video_outbuf_size, picture); + if (retcd < 0 ){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error encoding video"); + my_packet_unref(ffmpeg->pkt); +@@ -457,11 +462,12 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.size = retcd; + ffmpeg->pkt.data = video_outbuf; + +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; +- +- ffmpeg->pkt.pts = ffmpeg->picture->pts; +- ffmpeg->pkt.dts = ffmpeg->pkt.pts; ++ if (picture) { ++ if (picture->key_frame == 1) ++ ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; ++ ffmpeg->pkt.pts = picture->pts; ++ ffmpeg->pkt.dts = ffmpeg->pkt.pts; ++ } + + retcd = ffmpeg_write_packet(ffmpeg); + if (retcd < 0) { +@@ -817,7 +823,7 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + return 0; + } + +- retcd = ffmpeg_encode_video(ffmpeg); ++ retcd = ffmpeg_encode_video(ffmpeg, ffmpeg->picture); + if (retcd < 0){ + if (retcd != -2) + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); +@@ -957,6 +963,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ #ifdef HAVE_FFMPEG if (ffmpeg != NULL) { -+ ffmpeg_drain_codec(ffmpeg); ++ ffmpeg_encode_video(ffmpeg, NULL); // drain codec if (ffmpeg->tlapse != TIMELAPSE_APPEND) { av_write_trailer(ffmpeg->oc); } diff --git a/package/motion/enable-h264-omx-codec.patch b/package/motion/enable-h264-omx-codec.patch new file mode 100644 index 0000000000..90568ad640 --- /dev/null +++ b/package/motion/enable-h264-omx-codec.patch @@ -0,0 +1,13 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index a729cda..798c017 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -513,7 +513,7 @@ static int ffmpeg_codec_is_blacklisted(const char *codec_name){ + * - remove the "h264_omx" from this blacklist. + * More information: https://github.com/Motion-Project/motion/issues/433 + */ +- "h264_omx", ++ //"h264_omx", + }; + size_t i; + diff --git a/package/motion/preferred-encoder.patch b/package/motion/preferred-encoder.patch deleted file mode 100644 index 4b6471c303..0000000000 --- a/package/motion/preferred-encoder.patch +++ /dev/null @@ -1,151 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 87b4f75..f3c685a 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -236,12 +236,24 @@ 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 = malloc(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); -+ free(codec_name); - return -1; - } - -@@ -250,59 +262,61 @@ 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); -+ free(codec_name); - return -1; - } -+ free(codec_name); - 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,17 +324,20 @@ 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); -+ free(codec_name); - return -1; - } - - if (ffmpeg->oc->oformat->video_codec == MY_CODEC_ID_NONE) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Could not get the codec"); - ffmpeg_free_context(ffmpeg); -+ free(codec_name); - return -1; - } - -+ free(codec_name); - return 0; - } - -@@ -484,13 +501,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/package/motion/tune-h264-encode-quality.patch b/package/motion/tune-h264-encode-quality.patch deleted file mode 100644 index c989af5ccf..0000000000 --- a/package/motion/tune-h264-encode-quality.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/ffmpeg.c b/ffmpeg.c -index 87b4f75..4816adf 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -451,21 +451,30 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ - - static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ - -- char crf[4]; -- - 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) { -- ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); -+ if (ffmpeg->vbr <= 0) -+ ffmpeg->vbr = 45; // default to 45% quality -+ av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); -+ av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); -+ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0)) { -+ // H264 OMX encoder quality can only be controlled via bit_rate -+ // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor -+ ffmpeg->vbr = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->vbr) >> 7; -+ // Clip bit rate to min -+ if (ffmpeg->vbr < 4000) // magic number -+ ffmpeg->vbr = 4000; -+ ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; -+ ffmpeg->ctx_codec->bit_rate = ffmpeg->vbr; - } else { -- ffmpeg->vbr = 28; -+ // Control other H264 encoders quality via CRF -+ char crf[4]; -+ ffmpeg->vbr = (int)(( (100-ffmpeg->vbr) * 51)/100); -+ snprintf(crf, 4, "%d", ffmpeg->vbr); -+ av_dict_set(&ffmpeg->opts, "crf", crf, 0); - } -- 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); - } else { - /* The selection of 8000 in the else is a subjective number based upon viewing output files */ - if (ffmpeg->vbr > 0){ -@@ -474,7 +483,7 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ - ffmpeg->ctx_codec->global_quality=ffmpeg->vbr; - } - } -- MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "vbr/crf for codec: %d", ffmpeg->vbr); -+ MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "%s codec vbr/crf/bit_rate: %d", ffmpeg->codec->name, ffmpeg->vbr); - - return 0; - } From 7e50bcbcce12248de6626d0b451c992b4d2ddf34 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 18 Sep 2017 16:30:29 +1000 Subject: [PATCH 28/28] motion: write trailer even if codec drain fails --- package/motion/0013-drain-codec.patch | 55 +++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/package/motion/0013-drain-codec.patch b/package/motion/0013-drain-codec.patch index e9c17357cb..480403a1ea 100644 --- a/package/motion/0013-drain-codec.patch +++ b/package/motion/0013-drain-codec.patch @@ -1,11 +1,11 @@ -commit 9c604dc427804b9620044a2bdddca1b8c1831627 +commit ff55aecd6fb88a030790b494dcd55bd99cace52b Author: Joo Aun Saw -Date: Mon Sep 18 14:30:22 2017 +1000 +Date: Mon Sep 18 16:25:44 2017 +1000 drain codec at end of recording diff --git a/ffmpeg.c b/ffmpeg.c -index aa06bef..c690896 100644 +index aa06bef..ecdc3e5 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -350,7 +350,7 @@ static int ffmpeg_write_packet(struct ffmpeg *ffmpeg){ @@ -46,7 +46,20 @@ index aa06bef..c690896 100644 } if (retcd < 0 ){ av_strerror(retcd, errstr, sizeof(errstr)); -@@ -404,7 +409,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -385,7 +390,11 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); +- ffmpeg_free_context(ffmpeg); ++ /* Do not free ffmpeg context if we are draining codec. We still ++ * need to write trailer even if draining fails. ++ */ ++ if (picture != NULL) ++ ffmpeg_free_context(ffmpeg); + return -1; + } + } +@@ -404,7 +413,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ffmpeg->pkt.data = NULL; ffmpeg->pkt.size = 0; @@ -55,7 +68,20 @@ index aa06bef..c690896 100644 if (retcd < 0 ){ av_strerror(retcd, errstr, sizeof(errstr)); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error encoding video:%s",errstr); -@@ -441,7 +446,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -421,7 +430,11 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); +- ffmpeg_free_context(ffmpeg); ++ /* Do not free ffmpeg context if we are draining codec. We still ++ * need to write trailer even if draining fails. ++ */ ++ if (picture != NULL) ++ ffmpeg_free_context(ffmpeg); + return -1; + } + +@@ -441,7 +454,7 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; video_outbuf = mymalloc(video_outbuf_size); @@ -64,7 +90,7 @@ index aa06bef..c690896 100644 if (retcd < 0 ){ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error encoding video"); my_packet_unref(ffmpeg->pkt); -@@ -457,11 +462,12 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -457,11 +470,12 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ffmpeg->pkt.size = retcd; ffmpeg->pkt.data = video_outbuf; @@ -82,7 +108,20 @@ index aa06bef..c690896 100644 retcd = ffmpeg_write_packet(ffmpeg); if (retcd < 0) { -@@ -817,7 +823,7 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +@@ -469,7 +483,11 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); + free(video_outbuf); +- ffmpeg_free_context(ffmpeg); ++ /* Do not free ffmpeg context if we are draining codec. We still ++ * need to write trailer even if draining fails. ++ */ ++ if (picture != NULL) ++ ffmpeg_free_context(ffmpeg); + return -1; + } + +@@ -817,7 +835,7 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ return 0; } @@ -91,7 +130,7 @@ index aa06bef..c690896 100644 if (retcd < 0){ if (retcd != -2) MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); -@@ -957,6 +963,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ +@@ -957,6 +975,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ #ifdef HAVE_FFMPEG if (ffmpeg != NULL) {