From 8e4cece9e2b6aa4259da12fae52b544df7aa5da7 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 1 Jul 2019 15:20:38 +1000 Subject: [PATCH 01/17] ffmpeg: h264_v4l2m2m: pull in memeka's patches --- ...e-unnecessary-timeout-while-draining.patch | 54 ++++++++++++++++ ...fix-segmentation-fault-on-codec-exit.patch | 63 +++++++++++++++++++ ...ble-bit-rate-control-for-mfc-encoder.patch | 27 ++++++++ ...ge-number-of-buffers-for-mfc-encoder.patch | 34 ++++++++++ 4 files changed, 178 insertions(+) create mode 100644 package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch create mode 100644 package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch create mode 100644 package/ffmpeg/1003-avcodec-v4l2-enable-bit-rate-control-for-mfc-encoder.patch create mode 100644 package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch diff --git a/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch b/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch new file mode 100644 index 0000000000..bbf052c6b3 --- /dev/null +++ b/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch @@ -0,0 +1,54 @@ +commit d338ad5e95e6d7b3c4131418d5a92b4717135dec +Author: Jorge Ramirez-Ortiz +Date: Tue Oct 3 10:31:47 2017 +0200 + + avcodec/v4l2_context: remove unnecessary timeout while draining + + This timeout was introduced to work around a bug in the test platform + used to upstream the v4l2 support (DragonBoard 410c, Venus driver). + + Signed-off-by: memeka + +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index 652472fcd6..d5f9f8edac 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -261,17 +261,15 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) + if (V4L2_TYPE_IS_OUTPUT(ctx->type)) + pfd.events = POLLOUT | POLLWRNORM; + ++ if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) ++ pfd.events = POLLIN | POLLRDNORM | POLLPRI; ++ + for (;;) { + ret = poll(&pfd, 1, timeout); + if (ret > 0) + break; + if (errno == EINTR) + continue; +- +- /* timeout is being used to indicate last valid bufer when draining */ +- if (ctx_to_m2mctx(ctx)->draining) +- ctx->done = 1; +- + return NULL; + } + +@@ -559,7 +557,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame) + * 1. decoded frame available + * 2. an input buffer is ready to be dequeued + */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, -1); + if (!avbuf) { + if (ctx->done) + return AVERROR_EOF; +@@ -581,7 +579,7 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) + * 1. encoded packet available + * 2. an input buffer ready to be dequeued + */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, -1); + if (!avbuf) { + if (ctx->done) + return AVERROR_EOF; diff --git a/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch b/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch new file mode 100644 index 0000000000..e18a435b7e --- /dev/null +++ b/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch @@ -0,0 +1,63 @@ +commit 18d00a8264b42b9bf9c11b539557ea8e6186aa8e +Author: Jorge Ramirez-Ortiz +Date: Fri Oct 6 09:24:57 2017 +0200 + + avcodec/v4l2: fix segmentation fault on codec exit + + It occurs when the codec is closed while buffer references still + exist. This is a regression from the original patchset where support + for this use-case was implemented. + + Signed-off-by: memeka + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index ba70c5d14b..109f611c8a 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -219,8 +219,17 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) + return; + } + +- if (!atomic_load(&s->refcount)) +- ff_v4l2_m2m_codec_end(s->avctx); ++ if (!atomic_load(&s->refcount)) { ++ ++ ff_v4l2_context_release(&s->capture); ++ sem_destroy(&s->refsync); ++ ++ /* release the hardware */ ++ if (close(s->fd) < 0 ) ++ av_log(s->avctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno))); ++ ++ s->fd = -1; ++ } + } + + static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) +diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c +index bd96a6d979..b78e0315f6 100644 +--- a/libavcodec/v4l2_m2m.c ++++ b/libavcodec/v4l2_m2m.c +@@ -321,6 +321,9 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) + V4L2m2mContext* s = avctx->priv_data; + int ret; + ++ if (s->fd < 0) ++ return 0; ++ + ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); + if (ret) + av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); +@@ -331,8 +334,10 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) + + ff_v4l2_context_release(&s->output); + +- if (atomic_load(&s->refcount)) +- av_log(avctx, AV_LOG_ERROR, "ff_v4l2m2m_codec_end leaving pending buffers\n"); ++ if (atomic_load(&s->refcount)) { ++ av_log(avctx, AV_LOG_DEBUG, "ff_v4l2m2m_codec_end leaving pending buffers\n"); ++ return 0; ++ } + + ff_v4l2_context_release(&s->capture); + sem_destroy(&s->refsync); diff --git a/package/ffmpeg/1003-avcodec-v4l2-enable-bit-rate-control-for-mfc-encoder.patch b/package/ffmpeg/1003-avcodec-v4l2-enable-bit-rate-control-for-mfc-encoder.patch new file mode 100644 index 0000000000..7eee3bf041 --- /dev/null +++ b/package/ffmpeg/1003-avcodec-v4l2-enable-bit-rate-control-for-mfc-encoder.patch @@ -0,0 +1,27 @@ +commit 24ae67b3fb9e081b9306c2391a79b4388152332f +Author: memeka +Date: Thu Oct 19 13:22:18 2017 +1030 + + avcodec/v4l2: enable bit rate control for MFC encoder + + Signed-off-by: memeka + +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index e40a120b53..2c35f95847 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -183,8 +183,13 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) + + /* set ext ctrls */ + v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode"); ++ /* enable bit rate control */ ++ if (avctx->bit_rate > 1) { ++ v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE) , 1, "rate control"); ++ av_log(avctx, AV_LOG_INFO, "h264_v4l2m2m encoder: enabling bit rate control: %llu\n", avctx->bit_rate); ++ } + v4l2_set_ext_ctrl(s, MPEG_CID(BITRATE) , avctx->bit_rate, "bit rate"); +- v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size,"gop size"); ++ v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size, "gop size"); + + av_log(avctx, AV_LOG_DEBUG, + "Encoder Context: id (%d), profile (%d), frame rate(%d/%d), number b-frames (%d), " diff --git a/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch b/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch new file mode 100644 index 0000000000..2735e439a4 --- /dev/null +++ b/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch @@ -0,0 +1,34 @@ +commit 530a3fc31b515fe1cdcbbd03ca884c84d72580b1 +Author: memeka +Date: Thu Oct 19 13:23:34 2017 +1030 + + avcodec/v4l2: change number of buffers for MFC encoder + + Signed-off-by: memeka + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index 2d96f13954..266caa7bac 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -288,7 +288,7 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + static const AVOption options[] = { + V4L_M2M_DEFAULT_OPTS, + { "num_capture_buffers", "Number of buffers in the capture context", +- OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, ++ OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 16}, 16, INT_MAX, FLAGS }, + { NULL}, + }; + +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index 2c35f95847..ce4b45816e 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -325,7 +325,7 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) + static const AVOption options[] = { + V4L_M2M_DEFAULT_OPTS, + { "num_capture_buffers", "Number of buffers in the capture context", +- OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS }, ++ OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 8}, 8, INT_MAX, FLAGS }, + { NULL }, + }; + From aa7e6c1412cf6b804728fd3cde611d71a5c64723 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 1 Jul 2019 15:21:26 +1000 Subject: [PATCH 02/17] motion: patch to enable h264_v4l2m2m --- package/motion/0002-enable-h264-v4l2m2m.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 package/motion/0002-enable-h264-v4l2m2m.patch diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch new file mode 100644 index 0000000000..1596d34a19 --- /dev/null +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -0,0 +1,14 @@ +diff -rupEbwBN -x.git motion-release-4.2.2.org/ffmpeg.c motion-release-4.2.2/ffmpeg.c +--- motion-release-4.2.2.org/ffmpeg.c 2019-07-01 12:44:27.934954580 +1000 ++++ motion-release-4.2.2/ffmpeg.c 2019-07-01 15:08:24.346954580 +1000 +@@ -555,7 +555,9 @@ static int ffmpeg_set_quality(struct ffm + ffmpeg->quality = 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)) { ++ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || ++ (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0) || ++ (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0)) { + // H264 OMX encoder quality can only be controlled via bit_rate + // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor + ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->quality) >> 7); From 1ca74222178455e97965da44cd672fe7f98e2a9b Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 16 Jul 2019 11:38:58 +1000 Subject: [PATCH 03/17] xu4: upgrade to kernel 4.14 --- configs/odroidxu4_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/odroidxu4_defconfig b/configs/odroidxu4_defconfig index 678a35446b..1581e5a2b5 100644 --- a/configs/odroidxu4_defconfig +++ b/configs/odroidxu4_defconfig @@ -12,7 +12,7 @@ BR2_ROOTFS_OVERLAY="board/common/overlay board/odroidxu4/overlay" BR2_ROOTFS_POST_BUILD_SCRIPT="board/common/postscript.sh" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_TARBALL=y -BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://github.com/hardkernel/linux/archive/be592282a08a2493692448e365e46b52ac715b3f.tar.gz" +BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://github.com/hardkernel/linux/archive/4.14.127-164.tar.gz" BR2_LINUX_KERNEL_DEFCONFIG="odroidxu4" BR2_LINUX_KERNEL_DTS_SUPPORT=y BR2_LINUX_KERNEL_INTREE_DTS_NAME="exynos5422-odroidxu4" From 65f2815773f5da3d531f2103918c57a20e141518 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 15:40:30 +1000 Subject: [PATCH 04/17] ffmpeg: upgrade to version 4.1.4 --- ...e-unnecessary-timeout-while-draining.patch | 54 ---------------- ...fix-segmentation-fault-on-codec-exit.patch | 63 ------------------- ...ge-number-of-buffers-for-mfc-encoder.patch | 34 ---------- package/ffmpeg/ffmpeg.hash | 2 +- package/ffmpeg/ffmpeg.mk | 8 +-- 5 files changed, 2 insertions(+), 159 deletions(-) delete mode 100644 package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch delete mode 100644 package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch delete mode 100644 package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch diff --git a/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch b/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch deleted file mode 100644 index bbf052c6b3..0000000000 --- a/package/ffmpeg/1001-avcodec-v4l2-remove-unnecessary-timeout-while-draining.patch +++ /dev/null @@ -1,54 +0,0 @@ -commit d338ad5e95e6d7b3c4131418d5a92b4717135dec -Author: Jorge Ramirez-Ortiz -Date: Tue Oct 3 10:31:47 2017 +0200 - - avcodec/v4l2_context: remove unnecessary timeout while draining - - This timeout was introduced to work around a bug in the test platform - used to upstream the v4l2 support (DragonBoard 410c, Venus driver). - - Signed-off-by: memeka - -diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c -index 652472fcd6..d5f9f8edac 100644 ---- a/libavcodec/v4l2_context.c -+++ b/libavcodec/v4l2_context.c -@@ -261,17 +261,15 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout) - if (V4L2_TYPE_IS_OUTPUT(ctx->type)) - pfd.events = POLLOUT | POLLWRNORM; - -+ if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) -+ pfd.events = POLLIN | POLLRDNORM | POLLPRI; -+ - for (;;) { - ret = poll(&pfd, 1, timeout); - if (ret > 0) - break; - if (errno == EINTR) - continue; -- -- /* timeout is being used to indicate last valid bufer when draining */ -- if (ctx_to_m2mctx(ctx)->draining) -- ctx->done = 1; -- - return NULL; - } - -@@ -559,7 +557,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame) - * 1. decoded frame available - * 2. an input buffer is ready to be dequeued - */ -- avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, -1); - if (!avbuf) { - if (ctx->done) - return AVERROR_EOF; -@@ -581,7 +579,7 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) - * 1. encoded packet available - * 2. an input buffer ready to be dequeued - */ -- avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, -1); - if (!avbuf) { - if (ctx->done) - return AVERROR_EOF; diff --git a/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch b/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch deleted file mode 100644 index e18a435b7e..0000000000 --- a/package/ffmpeg/1002-avcodec-v4l2-fix-segmentation-fault-on-codec-exit.patch +++ /dev/null @@ -1,63 +0,0 @@ -commit 18d00a8264b42b9bf9c11b539557ea8e6186aa8e -Author: Jorge Ramirez-Ortiz -Date: Fri Oct 6 09:24:57 2017 +0200 - - avcodec/v4l2: fix segmentation fault on codec exit - - It occurs when the codec is closed while buffer references still - exist. This is a regression from the original patchset where support - for this use-case was implemented. - - Signed-off-by: memeka - -diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c -index ba70c5d14b..109f611c8a 100644 ---- a/libavcodec/v4l2_buffers.c -+++ b/libavcodec/v4l2_buffers.c -@@ -219,8 +219,17 @@ static void v4l2_free_buffer(void *opaque, uint8_t *unused) - return; - } - -- if (!atomic_load(&s->refcount)) -- ff_v4l2_m2m_codec_end(s->avctx); -+ if (!atomic_load(&s->refcount)) { -+ -+ ff_v4l2_context_release(&s->capture); -+ sem_destroy(&s->refsync); -+ -+ /* release the hardware */ -+ if (close(s->fd) < 0 ) -+ av_log(s->avctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno))); -+ -+ s->fd = -1; -+ } - } - - static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) -diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c -index bd96a6d979..b78e0315f6 100644 ---- a/libavcodec/v4l2_m2m.c -+++ b/libavcodec/v4l2_m2m.c -@@ -321,6 +321,9 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) - V4L2m2mContext* s = avctx->priv_data; - int ret; - -+ if (s->fd < 0) -+ return 0; -+ - ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); - if (ret) - av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); -@@ -331,8 +334,10 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) - - ff_v4l2_context_release(&s->output); - -- if (atomic_load(&s->refcount)) -- av_log(avctx, AV_LOG_ERROR, "ff_v4l2m2m_codec_end leaving pending buffers\n"); -+ if (atomic_load(&s->refcount)) { -+ av_log(avctx, AV_LOG_DEBUG, "ff_v4l2m2m_codec_end leaving pending buffers\n"); -+ return 0; -+ } - - ff_v4l2_context_release(&s->capture); - sem_destroy(&s->refsync); diff --git a/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch b/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch deleted file mode 100644 index 2735e439a4..0000000000 --- a/package/ffmpeg/1004-avcodec-v4l2-change-number-of-buffers-for-mfc-encoder.patch +++ /dev/null @@ -1,34 +0,0 @@ -commit 530a3fc31b515fe1cdcbbd03ca884c84d72580b1 -Author: memeka -Date: Thu Oct 19 13:23:34 2017 +1030 - - avcodec/v4l2: change number of buffers for MFC encoder - - Signed-off-by: memeka - -diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c -index 2d96f13954..266caa7bac 100644 ---- a/libavcodec/v4l2_m2m_dec.c -+++ b/libavcodec/v4l2_m2m_dec.c -@@ -288,7 +288,7 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) - static const AVOption options[] = { - V4L_M2M_DEFAULT_OPTS, - { "num_capture_buffers", "Number of buffers in the capture context", -- OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 20}, 20, INT_MAX, FLAGS }, -+ OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 16}, 16, INT_MAX, FLAGS }, - { NULL}, - }; - -diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c -index 2c35f95847..ce4b45816e 100644 ---- a/libavcodec/v4l2_m2m_enc.c -+++ b/libavcodec/v4l2_m2m_enc.c -@@ -325,7 +325,7 @@ static av_cold int v4l2_encode_init(AVCodecContext *avctx) - static const AVOption options[] = { - V4L_M2M_DEFAULT_OPTS, - { "num_capture_buffers", "Number of buffers in the capture context", -- OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS }, -+ OFFSET(capture.num_buffers), AV_OPT_TYPE_INT, {.i64 = 8}, 8, INT_MAX, FLAGS }, - { NULL }, - }; - diff --git a/package/ffmpeg/ffmpeg.hash b/package/ffmpeg/ffmpeg.hash index e00c4ec56c..f27eaa5706 100644 --- a/package/ffmpeg/ffmpeg.hash +++ b/package/ffmpeg/ffmpeg.hash @@ -1,5 +1,5 @@ # Locally calculated -sha256 741cbd6394eaed370774ca4cc089eaafbc54d0824b9aa360d4b3b0cbcbc4a92c ffmpeg-3.4.5.tar.xz +sha256 f1f049a82fcfbf156564e73a3935d7e750891fab2abf302e735104fd4050a7e1 ffmpeg-4.1.4.tar.xz sha256 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643 COPYING.GPLv2 sha256 b634ab5640e258563c536e658cad87080553df6f34f62269a21d554844e58bfe COPYING.LGPLv2.1 sha256 73d99bc83313fff665b426d6672b4e0479102bc402fe22314ac9ce94a38aa5ff LICENSE.md diff --git a/package/ffmpeg/ffmpeg.mk b/package/ffmpeg/ffmpeg.mk index b86d465df8..349ed20822 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -4,7 +4,7 @@ # ################################################################################ -FFMPEG_VERSION = 3.4.5 +FFMPEG_VERSION = 4.1.4 FFMPEG_SOURCE = ffmpeg-$(FFMPEG_VERSION).tar.xz FFMPEG_SITE = http://ffmpeg.org/releases FFMPEG_INSTALL_STAGING = YES @@ -84,12 +84,6 @@ else FFMPEG_CONF_OPTS += --disable-ffplay endif -ifeq ($(BR2_PACKAGE_FFMPEG_FFSERVER),y) -FFMPEG_CONF_OPTS += --enable-ffserver -else -FFMPEG_CONF_OPTS += --disable-ffserver -endif - ifeq ($(BR2_PACKAGE_FFMPEG_AVRESAMPLE),y) FFMPEG_CONF_OPTS += --enable-avresample else From 74f5b58d946af1f317209726b94d3af30aaa194a Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 15:41:56 +1000 Subject: [PATCH 05/17] ffmpeg: v4l2_m2m: fix output media file missing keyframe at timestamp 0 --- ...se-joined-with-1st-frame-header-mode.patch | 19 ++++++++++++ ...-add-timeout-when-dequeueing-buffers.patch | 30 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch create mode 100644 package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch diff --git a/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch b/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch new file mode 100644 index 0000000000..4aea0ede30 --- /dev/null +++ b/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch @@ -0,0 +1,19 @@ +commit e370306deb9c48f4daa4ae4d622a7bd8b3828bef +Author: Joo Aun Saw +Date: Mon Aug 19 15:20:52 2019 +1000 + + avcodec/v4l2_m2m_enc: use joined with 1st frame header mode + +diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c +index 354d78babb..32aaaf18fb 100644 +--- a/libavcodec/v4l2_m2m_enc.c ++++ b/libavcodec/v4l2_m2m_enc.c +@@ -174,7 +174,7 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) + v4l2_set_timeperframe(s, avctx->framerate.num, avctx->framerate.den); + + /* set ext ctrls */ +- v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode"); ++ v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_JOINED_WITH_1ST_FRAME), "header mode"); + /* enable bit rate control */ + if (avctx->bit_rate > 1) { + v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE) , 1, "rate control"); diff --git a/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch new file mode 100644 index 0000000000..efb15f75dc --- /dev/null +++ b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch @@ -0,0 +1,30 @@ +commit 05ee1b8f65e4029fcad832743701712a1a000ea3 +Author: Joo Aun Saw +Date: Mon Aug 19 15:21:30 2019 +1000 + + avcodec/v4l2: add timeout when dequeueing buffers + + Add timeout to prevent lock up when buffer queue is empty. + +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index efcb0426e4..8f9420e28d 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -580,7 +580,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame) + * 1. decoded frame available + * 2. an input buffer is ready to be dequeued + */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, -1); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 200); + if (!avbuf) { + if (ctx->done) + return AVERROR_EOF; +@@ -600,7 +600,7 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) + * 1. encoded packet available + * 2. an input buffer ready to be dequeued + */ +- avbuf = v4l2_dequeue_v4l2buf(ctx, -1); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 200); + if (!avbuf) { + if (ctx->done) + return AVERROR_EOF; From 0311e9155e4a2e751b65523e4bbde8e1e7fe0e13 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 16:44:28 +1000 Subject: [PATCH 06/17] motion: special handling of h264_v4l2m2m encoder --- package/motion/0002-enable-h264-v4l2m2m.patch | 168 +++++++++++++++++- .../0003-fix-h264-v4l2m2m-drain-error.patch | 35 ++++ 2 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 package/motion/0003-fix-h264-v4l2m2m-drain-error.patch diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch index 1596d34a19..5b41c9b667 100644 --- a/package/motion/0002-enable-h264-v4l2m2m.patch +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -1,14 +1,168 @@ -diff -rupEbwBN -x.git motion-release-4.2.2.org/ffmpeg.c motion-release-4.2.2/ffmpeg.c ---- motion-release-4.2.2.org/ffmpeg.c 2019-07-01 12:44:27.934954580 +1000 -+++ motion-release-4.2.2/ffmpeg.c 2019-07-01 15:08:24.346954580 +1000 -@@ -555,7 +555,9 @@ static int ffmpeg_set_quality(struct ffm +commit cbf86207346d9f1bc36005c2a6342bacf4bcc3e4 +Author: Joo Aun Saw +Date: Mon Aug 19 16:33:08 2019 +1000 + + support h264_v4l2m2m encoder + +diff --git a/ffmpeg.c b/ffmpeg.c +index 3f731ca..beb87b1 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -555,7 +555,9 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ ffmpeg->quality = 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)) { -+ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || -+ (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0) || -+ (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0)) { ++ if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || ++ (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0) || ++ (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0)) { // H264 OMX encoder quality can only be controlled via bit_rate // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->quality) >> 7); +@@ -596,6 +598,10 @@ static int ffmpeg_codec_is_blacklisted(const char *codec_name){ + * More information: https://github.com/Motion-Project/motion/issues/433 + */ + "h264_omx", ++#if (LIBAVCODEC_VERSION_MAJOR < 57) ++ /* h264_v4l2m2m does not exist on old versions of ffmpeg. */ ++ "h264_v4l2m2m", ++#endif + }; + size_t i; + +@@ -702,7 +708,10 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ + ffmpeg->ctx_codec->height = ffmpeg->height; + ffmpeg->ctx_codec->time_base.num = 1; + ffmpeg->ctx_codec->time_base.den = ffmpeg->fps; +- ffmpeg->ctx_codec->pix_fmt = MY_PIX_FMT_YUV420P; ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) ++ ffmpeg->ctx_codec->pix_fmt = AV_PIX_FMT_NV21; ++ else ++ ffmpeg->ctx_codec->pix_fmt = MY_PIX_FMT_YUV420P; + ffmpeg->ctx_codec->max_b_frames = 0; + if (strcmp(ffmpeg->codec_name, "ffv1") == 0){ + ffmpeg->ctx_codec->strict_std_compliance = -2; +@@ -768,6 +777,65 @@ static int ffmpeg_set_stream(struct ffmpeg *ffmpeg){ + + } + ++ ++static int alloc_video_buffer(AVFrame *frame, int align) ++{ ++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); ++ int ret, i, padded_height; ++ int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align); ++ ++ if (!desc) ++ return AVERROR(EINVAL); ++ ++ if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0) ++ return ret; ++ ++ if (!frame->linesize[0]) { ++ if (align <= 0) ++ align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */ ++ ++ for(i=1; i<=align; i+=i) { ++ ret = av_image_fill_linesizes(frame->linesize, frame->format, ++ FFALIGN(frame->width, i)); ++ if (ret < 0) ++ return ret; ++ if (!(frame->linesize[0] & (align-1))) ++ break; ++ } ++ ++ for (i = 0; i < 4 && frame->linesize[i]; i++) ++ frame->linesize[i] = FFALIGN(frame->linesize[i], align); ++ } ++ ++ padded_height = FFALIGN(frame->height, 32); ++ if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height, ++ NULL, frame->linesize)) < 0) ++ return ret; ++ ++ frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding); ++ if (!frame->buf[0]) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ frame->buf[1] = av_buffer_alloc(ret + 4*plane_padding); ++ if (!frame->buf[1]) { ++ ret = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ frame->data[0] = frame->buf[0]->data; ++ frame->data[1] = frame->buf[1]->data; ++ frame->data[2] = frame->data[1] + ((frame->width * padded_height) / 4); ++ ++ frame->extended_data = frame->data; ++ ++ return 0; ++fail: ++ av_frame_unref(frame); ++ return ret; ++} ++ ++ + static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ + + ffmpeg->picture = my_frame_alloc(); +@@ -789,6 +857,15 @@ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ + ffmpeg->picture->width = ffmpeg->ctx_codec->width; + ffmpeg->picture->height = ffmpeg->ctx_codec->height; + ++ // h264_v4l2m2m encoder expects video buffer to be allocated ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { ++ if (alloc_video_buffer(ffmpeg->picture, 32)) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers")); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ } ++ + return 0; + + } +@@ -1365,9 +1442,38 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s + } + + /* Setup pointers and line widths. */ +- ffmpeg->picture->data[0] = image; +- ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); +- ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) / 4); ++ // Some encoders look for the image in ffmpeg->picture->buf ++ if (ffmpeg->picture->buf[0] == NULL) ++ ffmpeg->picture->data[0] = image; ++ else ++ memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ ++ if (ffmpeg->picture->buf[1] == NULL) { ++ // assume YUV420P format ++ ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4); ++ } else { ++ int cr_len = ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4; ++ int cb_len = cr_len; ++ unsigned char *imagecr = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ unsigned char *imagecb = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) + cr_len; ++ if (ffmpeg->ctx_codec->pix_fmt == AV_PIX_FMT_NV21) { ++ int x; ++ int y; ++ for (y = 0; y < ffmpeg->ctx_codec->height; y++) { ++ for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) { ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imagecb; ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *imagecr; ++ imagecb++; ++ imagecr++; ++ } ++ } ++ } else { ++ // assume YUV420P format ++ memcpy(&ffmpeg->picture->data[1][0], imagecr, cr_len); ++ memcpy(&ffmpeg->picture->data[1][cr_len], imagecb, cb_len); ++ } ++ } + + ffmpeg->gop_cnt ++; + if (ffmpeg->gop_cnt == ffmpeg->ctx_codec->gop_size ){ diff --git a/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch b/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch new file mode 100644 index 0000000000..0937f8f9a6 --- /dev/null +++ b/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch @@ -0,0 +1,35 @@ +commit d1aad9ec2b37560ddf2b2a362e30882adce8fb94 +Author: Joo Aun Saw +Date: Mon Aug 19 16:36:30 2019 +1000 + + fix h264_v4l2m2m encoder draining error + + When h264_v4l2m2m encoder is drained, it sets packet pts and size to + zero rather than returning AVERROR_EOF. + +diff --git a/ffmpeg.c b/ffmpeg.c +index beb87b1..a3a8701 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -968,11 +968,16 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ + my_packet_unref(ffmpeg->pkt); + return -1; + } +- retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); +- if (retcd < 0) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO +- ,_("Error writing draining video frame")); +- return -1; ++ // v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EOF ++ if ((ffmpeg->pkt.pts > 0) && (ffmpeg->pkt.size > 0)) { ++ retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); ++ if (retcd < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO ++ ,_("Error writing draining video frame")); ++ return -1; ++ } ++ } else { ++ recv_cd = AVERROR_EOF; + } + } + my_packet_unref(ffmpeg->pkt); From 79c43680095094c098a572b0c2b451911b0a5aea Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 16:44:59 +1000 Subject: [PATCH 07/17] motion: update h264_omx unblacklist patch --- .../9900-unblacklist-h264-omx-encoder.patch | 19 +++++++++++++++++++ package/motion/enable-h264-omx-codec.patch | 13 ------------- 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 package/motion/9900-unblacklist-h264-omx-encoder.patch delete mode 100644 package/motion/enable-h264-omx-codec.patch diff --git a/package/motion/9900-unblacklist-h264-omx-encoder.patch b/package/motion/9900-unblacklist-h264-omx-encoder.patch new file mode 100644 index 0000000000..38018ba37f --- /dev/null +++ b/package/motion/9900-unblacklist-h264-omx-encoder.patch @@ -0,0 +1,19 @@ +commit c20e58b27aaa24b1a800e3cf73de1d3311d8987f +Author: Joo Aun Saw +Date: Mon Aug 19 16:38:59 2019 +1000 + + enable h264_omx encoder + +diff --git a/ffmpeg.c b/ffmpeg.c +index a3a8701..b9b58de 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -597,7 +597,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", + #if (LIBAVCODEC_VERSION_MAJOR < 57) + /* h264_v4l2m2m does not exist on old versions of ffmpeg. */ + "h264_v4l2m2m", diff --git a/package/motion/enable-h264-omx-codec.patch b/package/motion/enable-h264-omx-codec.patch deleted file mode 100644 index 90568ad640..0000000000 --- a/package/motion/enable-h264-omx-codec.patch +++ /dev/null @@ -1,13 +0,0 @@ -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; - From ef90015cac20f9fa97dbcd18769f0036a90bc882 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 16:58:52 +1000 Subject: [PATCH 08/17] ffmpeg: add handling for nv21 and yuv420p --- ...rs-add-handling-for-NV21-and-YUV420P.patch | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 package/ffmpeg/1007-v4l2-buffers-add-handling-for-NV21-and-YUV420P.patch diff --git a/package/ffmpeg/1007-v4l2-buffers-add-handling-for-NV21-and-YUV420P.patch b/package/ffmpeg/1007-v4l2-buffers-add-handling-for-NV21-and-YUV420P.patch new file mode 100644 index 0000000000..c669ebf6f9 --- /dev/null +++ b/package/ffmpeg/1007-v4l2-buffers-add-handling-for-NV21-and-YUV420P.patch @@ -0,0 +1,41 @@ +commit 0550486542f4c4628abf9e5cf1090c8f328f215f +Author: Dave Stevenson +Date: Thu Mar 22 16:01:35 2018 +0000 + + v4l2_buffers: Add handling for NV21 and YUV420P + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index aef911f..0f4dbb2 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -321,11 +321,21 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) + /* 1.1 fixup special cases */ + switch (avbuf->context->av_pix_fmt) { + case AV_PIX_FMT_NV12: ++ case AV_PIX_FMT_NV21: + if (avbuf->num_planes > 1) + break; + frame->linesize[1] = avbuf->plane_info[0].bytesperline; + frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; + break; ++ case AV_PIX_FMT_YUV420P: ++ /* No YV12? support? */ ++ if (avbuf->num_planes > 1) ++ break; ++ frame->linesize[1] = avbuf->plane_info[0].bytesperline >> 1; ++ frame->linesize[2] = avbuf->plane_info[0].bytesperline >> 1; ++ frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; ++ frame->data[2] = frame->data[1] + ((avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height) >> 2); ++ break; + default: + break; + } +@@ -468,6 +478,7 @@ int ff_v4l2_buffer_enqueue(V4L2Buffer* avbuf) + + avbuf->buf.flags = avbuf->flags; + ++ av_log(NULL, AV_LOG_ERROR, "ff_v4l2_buffer_enqueue: VIDIOC_QBUF : fd %d, index %u type %u\n", buf_to_m2mctx(avbuf)->fd, avbuf->buf.index, avbuf->buf.type); + ret = ioctl(buf_to_m2mctx(avbuf)->fd, VIDIOC_QBUF, &avbuf->buf); + if (ret < 0) + return AVERROR(errno); + From cc5891feb27675b41df7940dcb00fc52df002f83 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 23:50:36 +1000 Subject: [PATCH 09/17] ffmpeg: fix upgrade 4.1.4 --- package/ffmpeg/0001-ffmpeg-pthreads.patch | 4 +- ...cenc-Fix-building-with-libfdk-aac-v2.patch | 100 ------------------ ...stently-use-a-proper-version-check-m.patch | 99 ----------------- ...dk-aac-Don-t-use-defined-in-a-define.patch | 72 ------------- 4 files changed, 2 insertions(+), 273 deletions(-) delete mode 100644 package/ffmpeg/0002-libfdk-aacenc-Fix-building-with-libfdk-aac-v2.patch delete mode 100644 package/ffmpeg/0003-libfdk-aac-Consistently-use-a-proper-version-check-m.patch delete mode 100644 package/ffmpeg/0004-libfdk-aac-Don-t-use-defined-in-a-define.patch diff --git a/package/ffmpeg/0001-ffmpeg-pthreads.patch b/package/ffmpeg/0001-ffmpeg-pthreads.patch index c6d75d2297..0ad5903ecb 100644 --- a/package/ffmpeg/0001-ffmpeg-pthreads.patch +++ b/package/ffmpeg/0001-ffmpeg-pthreads.patch @@ -27,8 +27,8 @@ index c86e578..76523c8 100755 qsvdec_select="qsv" qsvenc_select="qsv" vaapi_encode_deps="vaapi" --v4l2_m2m_deps_any="linux_videodev2_h" -+v4l2_m2m_deps="linux_videodev2_h pthreads" +-v4l2_m2m_deps="linux_videodev2_h sem_timedwait" ++v4l2_m2m_deps="linux_videodev2_h sem_timedwait pthreads" hwupload_cuda_filter_deps="cuda" scale_npp_filter_deps="cuda libnpp" diff --git a/package/ffmpeg/0002-libfdk-aacenc-Fix-building-with-libfdk-aac-v2.patch b/package/ffmpeg/0002-libfdk-aacenc-Fix-building-with-libfdk-aac-v2.patch deleted file mode 100644 index 3f452242fa..0000000000 --- a/package/ffmpeg/0002-libfdk-aacenc-Fix-building-with-libfdk-aac-v2.patch +++ /dev/null @@ -1,100 +0,0 @@ -From c60fb550302878aba7e86037451f7996e8069289 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Martin=20Storsj=C3=B6?= -Date: Fri, 31 Aug 2018 14:25:30 +0300 -Subject: [PATCH] libfdk-aacenc: Fix building with libfdk-aac v2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When flushing the encoder, we now need to provide non-null buffer -parameters for everything, even if they are unused. - -The encoderDelay parameter has been replaced by two, nDelay and -nDelayCore. - -Downloaded from -http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=141c960e21d2860e354f9b90df136184dd00a9a8 - -Signed-off-by: Martin Storsjö -[Bernd: rebased for ffmpeg 3.4.5] -Signed-off-by: Bernd Kuhls ---- - libavcodec/libfdk-aacenc.c | 34 +++++++++++++++++++++++++--------- - 1 file changed, 25 insertions(+), 9 deletions(-) - -diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c -index 0e2051b468..f5adb407ed 100644 ---- a/libavcodec/libfdk-aacenc.c -+++ b/libavcodec/libfdk-aacenc.c -@@ -26,6 +26,11 @@ - #include "audio_frame_queue.h" - #include "internal.h" - -+#define FDKENC_VER_AT_LEAST(vl0, vl1) \ -+ (defined(AACENCODER_LIB_VL0) && \ -+ ((AACENCODER_LIB_VL0 > vl0) || \ -+ (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1))) -+ - typedef struct AACContext { - const AVClass *class; - HANDLE_AACENCODER handle; -@@ -286,7 +291,11 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) - } - - avctx->frame_size = info.frameLength; -+#if FDKENC_VER_AT_LEAST(4, 0) -+ avctx->initial_padding = info.nDelay; -+#else - avctx->initial_padding = info.encoderDelay; -+#endif - ff_af_queue_init(avctx, &s->afq); - - if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { -@@ -319,28 +328,35 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, - int out_buffer_size, out_buffer_element_size; - void *in_ptr, *out_ptr; - int ret; -+ uint8_t dummy_buf[1]; - AACENC_ERROR err; - - /* handle end-of-stream small frame and flushing */ - if (!frame) { -+ /* Must be a non-null pointer, even if it's a dummy. We could use -+ * the address of anything else on the stack as well. */ -+ in_ptr = dummy_buf; -+ in_buffer_size = 0; -+ - in_args.numInSamples = -1; - } else { -- in_ptr = frame->data[0]; -- in_buffer_size = 2 * avctx->channels * frame->nb_samples; -- in_buffer_element_size = 2; -+ in_ptr = frame->data[0]; -+ in_buffer_size = 2 * avctx->channels * frame->nb_samples; - -- in_args.numInSamples = avctx->channels * frame->nb_samples; -- in_buf.numBufs = 1; -- in_buf.bufs = &in_ptr; -- in_buf.bufferIdentifiers = &in_buffer_identifier; -- in_buf.bufSizes = &in_buffer_size; -- in_buf.bufElSizes = &in_buffer_element_size; -+ in_args.numInSamples = avctx->channels * frame->nb_samples; - - /* add current frame to the queue */ - if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) - return ret; - } - -+ in_buffer_element_size = 2; -+ in_buf.numBufs = 1; -+ in_buf.bufs = &in_ptr; -+ in_buf.bufferIdentifiers = &in_buffer_identifier; -+ in_buf.bufSizes = &in_buffer_size; -+ in_buf.bufElSizes = &in_buffer_element_size; -+ - /* The maximum packet size is 6144 bits aka 768 bytes per channel. */ - if ((ret = ff_alloc_packet2(avctx, avpkt, FFMAX(8192, 768 * avctx->channels), 0)) < 0) - return ret; --- -2.20.1 - diff --git a/package/ffmpeg/0003-libfdk-aac-Consistently-use-a-proper-version-check-m.patch b/package/ffmpeg/0003-libfdk-aac-Consistently-use-a-proper-version-check-m.patch deleted file mode 100644 index c358a045d1..0000000000 --- a/package/ffmpeg/0003-libfdk-aac-Consistently-use-a-proper-version-check-m.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 48be4c81e0ad081edab65e133e6e1bdec7de3b55 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Martin=20Storsj=C3=B6?= -Date: Tue, 4 Sep 2018 08:29:37 +0300 -Subject: [PATCH] libfdk-aac: Consistently use a proper version check macro for - detecting features -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -libfdk-aac: Consistently use a proper version check macro for detecting features - -The previous version checks checked explicitly for the version -where the version define was added to the installed headers, -making an "#ifdef AACDECODER_LIB_VL0" enough. Now that we have -a need for more diverse version checks than this, convert all checks -to such checks. - -Downloaded from -http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=ffb9b7a6bab6c6bfd3dd9a7c32e3724209824999 - -Signed-off-by: Martin Storsjö -Signed-off-by: Bernd Kuhls ---- - libavcodec/libfdk-aacdec.c | 13 ++++++++----- - libavcodec/libfdk-aacenc.c | 6 +++--- - 2 files changed, 11 insertions(+), 8 deletions(-) - -diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c -index 2857b9453f..ef51184ebd 100644 ---- a/libavcodec/libfdk-aacdec.c -+++ b/libavcodec/libfdk-aacdec.c -@@ -25,9 +25,12 @@ - #include "avcodec.h" - #include "internal.h" - --/* The version macro is introduced the same time as the setting enum was -- * changed, so this check should suffice. */ --#ifndef AACDECODER_LIB_VL0 -+#define FDKDEC_VER_AT_LEAST(vl0, vl1) \ -+ (defined(AACDECODER_LIB_VL0) && \ -+ ((AACDECODER_LIB_VL0 > vl0) || \ -+ (AACDECODER_LIB_VL0 == vl0 && AACDECODER_LIB_VL1 >= vl1))) -+ -+#if !FDKDEC_VER_AT_LEAST(2, 5) // < 2.5.10 - #define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS - #endif - -@@ -72,7 +75,7 @@ static const AVOption fdk_aac_dec_options[] = { - OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, - { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", - OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, --#ifdef AACDECODER_LIB_VL0 -+#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 - { "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD }, - #endif - { NULL } -@@ -293,7 +296,7 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) - } - } - --#ifdef AACDECODER_LIB_VL0 -+#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 - if (aacDecoder_SetParam(s->handle, AAC_PCM_LIMITER_ENABLE, s->level_limit) != AAC_DEC_OK) { - av_log(avctx, AV_LOG_ERROR, "Unable to set in signal level limiting in the decoder\n"); - return AVERROR_UNKNOWN; -diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c -index f5adb407ed..91dcb5a1b9 100644 ---- a/libavcodec/libfdk-aacenc.c -+++ b/libavcodec/libfdk-aacenc.c -@@ -156,7 +156,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) - case 6: mode = MODE_1_2_2_1; sce = 2; cpe = 2; break; - /* The version macro is introduced the same time as the 7.1 support, so this - should suffice. */ --#ifdef AACENCODER_LIB_VL0 -+#if FDKENC_VER_AT_LEAST(3, 4) // 3.4.12 - case 8: - sce = 2; - cpe = 3; -@@ -291,7 +291,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) - } - - avctx->frame_size = info.frameLength; --#if FDKENC_VER_AT_LEAST(4, 0) -+#if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0 - avctx->initial_padding = info.nDelay; - #else - avctx->initial_padding = info.encoderDelay; -@@ -412,7 +412,7 @@ static const uint64_t aac_channel_layout[] = { - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT0_BACK, - AV_CH_LAYOUT_5POINT1_BACK, --#ifdef AACENCODER_LIB_VL0 -+#if FDKENC_VER_AT_LEAST(3, 4) // 3.4.12 - AV_CH_LAYOUT_7POINT1_WIDE_BACK, - AV_CH_LAYOUT_7POINT1, - #endif --- -2.20.1 - diff --git a/package/ffmpeg/0004-libfdk-aac-Don-t-use-defined-in-a-define.patch b/package/ffmpeg/0004-libfdk-aac-Don-t-use-defined-in-a-define.patch deleted file mode 100644 index 30357b91e1..0000000000 --- a/package/ffmpeg/0004-libfdk-aac-Don-t-use-defined-in-a-define.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 452746d80fdaaaf1b546860eb78449c6de3678d7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Martin=20Storsj=C3=B6?= -Date: Wed, 12 Sep 2018 20:03:12 +0300 -Subject: [PATCH] libfdk-aac: Don't use defined() in a #define -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -libfdk-aac: Don't use defined() in a #define - -MSVC expands the preprocessor directives differently, making the -version check fail in the previous form. - -Clang can warn about this with -Wexpansion-to-defined (not currently -enabled by default): -warning: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined] - -Downloaded from -http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=2a9e1c122eed66be1b26b747342b848300b226c7 - -Signed-off-by: Martin Storsjö -Signed-off-by: Bernd Kuhls ---- - libavcodec/libfdk-aacdec.c | 9 ++++++--- - libavcodec/libfdk-aacenc.c | 9 ++++++--- - 2 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c -index ef51184ebd..0fbab36463 100644 ---- a/libavcodec/libfdk-aacdec.c -+++ b/libavcodec/libfdk-aacdec.c -@@ -25,10 +25,13 @@ - #include "avcodec.h" - #include "internal.h" - -+#ifdef AACDECODER_LIB_VL0 - #define FDKDEC_VER_AT_LEAST(vl0, vl1) \ -- (defined(AACDECODER_LIB_VL0) && \ -- ((AACDECODER_LIB_VL0 > vl0) || \ -- (AACDECODER_LIB_VL0 == vl0 && AACDECODER_LIB_VL1 >= vl1))) -+ ((AACDECODER_LIB_VL0 > vl0) || \ -+ (AACDECODER_LIB_VL0 == vl0 && AACDECODER_LIB_VL1 >= vl1)) -+#else -+#define FDKDEC_VER_AT_LEAST(vl0, vl1) 0 -+#endif - - #if !FDKDEC_VER_AT_LEAST(2, 5) // < 2.5.10 - #define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS -diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c -index 91dcb5a1b9..8349e56dcb 100644 ---- a/libavcodec/libfdk-aacenc.c -+++ b/libavcodec/libfdk-aacenc.c -@@ -26,10 +26,13 @@ - #include "audio_frame_queue.h" - #include "internal.h" - -+#ifdef AACENCODER_LIB_VL0 - #define FDKENC_VER_AT_LEAST(vl0, vl1) \ -- (defined(AACENCODER_LIB_VL0) && \ -- ((AACENCODER_LIB_VL0 > vl0) || \ -- (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1))) -+ ((AACENCODER_LIB_VL0 > vl0) || \ -+ (AACENCODER_LIB_VL0 == vl0 && AACENCODER_LIB_VL1 >= vl1)) -+#else -+#define FDKENC_VER_AT_LEAST(vl0, vl1) 0 -+#endif - - typedef struct AACContext { - const AVClass *class; --- -2.20.1 - From 2c11b23fa7362dfc1382f20edb2aa33861c9b390 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 23:52:00 +1000 Subject: [PATCH 10/17] Revert "motion: update h264_omx unblacklist patch" This reverts commit 79c43680095094c098a572b0c2b451911b0a5aea. --- .../9900-unblacklist-h264-omx-encoder.patch | 19 ------------------- package/motion/enable-h264-omx-codec.patch | 13 +++++++++++++ 2 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 package/motion/9900-unblacklist-h264-omx-encoder.patch create mode 100644 package/motion/enable-h264-omx-codec.patch diff --git a/package/motion/9900-unblacklist-h264-omx-encoder.patch b/package/motion/9900-unblacklist-h264-omx-encoder.patch deleted file mode 100644 index 38018ba37f..0000000000 --- a/package/motion/9900-unblacklist-h264-omx-encoder.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit c20e58b27aaa24b1a800e3cf73de1d3311d8987f -Author: Joo Aun Saw -Date: Mon Aug 19 16:38:59 2019 +1000 - - enable h264_omx encoder - -diff --git a/ffmpeg.c b/ffmpeg.c -index a3a8701..b9b58de 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -597,7 +597,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", - #if (LIBAVCODEC_VERSION_MAJOR < 57) - /* h264_v4l2m2m does not exist on old versions of ffmpeg. */ - "h264_v4l2m2m", 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; + From 223f55aa98b928084c59310ccbdbf4e3b26db6f4 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Mon, 19 Aug 2019 23:55:20 +1000 Subject: [PATCH 11/17] motion: unblacklist h264_v4l2m2m --- package/motion/0002-enable-h264-v4l2m2m.patch | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch index 5b41c9b667..416ab8d279 100644 --- a/package/motion/0002-enable-h264-v4l2m2m.patch +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -19,17 +19,6 @@ index 3f731ca..beb87b1 100644 // H264 OMX encoder quality can only be controlled via bit_rate // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->quality) >> 7); -@@ -596,6 +598,10 @@ static int ffmpeg_codec_is_blacklisted(const char *codec_name){ - * More information: https://github.com/Motion-Project/motion/issues/433 - */ - "h264_omx", -+#if (LIBAVCODEC_VERSION_MAJOR < 57) -+ /* h264_v4l2m2m does not exist on old versions of ffmpeg. */ -+ "h264_v4l2m2m", -+#endif - }; - size_t i; - @@ -702,7 +708,10 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ ffmpeg->ctx_codec->height = ffmpeg->height; ffmpeg->ctx_codec->time_base.num = 1; From bbbc89cca9bb8c18586f8b3cf3ea3c48eff4268c Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 20 Aug 2019 00:04:20 +1000 Subject: [PATCH 12/17] ffmpeg: reduce v4l2 buffer dequeue timeout --- ...006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch index efb15f75dc..bd39b9587f 100644 --- a/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch +++ b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch @@ -15,7 +15,7 @@ index efcb0426e4..8f9420e28d 100644 * 2. an input buffer is ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 200); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 50); if (!avbuf) { if (ctx->done) return AVERROR_EOF; @@ -24,7 +24,7 @@ index efcb0426e4..8f9420e28d 100644 * 2. an input buffer ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 200); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 50); if (!avbuf) { if (ctx->done) return AVERROR_EOF; From ee9e54d45d37144af6240061782334ca8926efe4 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Tue, 27 Aug 2019 01:37:15 +1000 Subject: [PATCH 13/17] motion: decouple avcodec send and receive --- ...01-decouple-avcodec-send-and-receive.patch | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 package/motion/1001-decouple-avcodec-send-and-receive.patch diff --git a/package/motion/1001-decouple-avcodec-send-and-receive.patch b/package/motion/1001-decouple-avcodec-send-and-receive.patch new file mode 100644 index 0000000000..54e9c4a493 --- /dev/null +++ b/package/motion/1001-decouple-avcodec-send-and-receive.patch @@ -0,0 +1,171 @@ +commit b9b521dc5d6179e8570d826e00728130144e3902 +Author: Joo Aun Saw +Date: Tue Aug 27 01:09:43 2019 +1000 + + ffmpeg: decouple avcodec send and receive + +diff --git a/ffmpeg.c b/ffmpeg.c +index 6b5459d..18b2894 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -378,6 +378,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)) +@@ -392,21 +401,31 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ,_("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 +- av_strerror(retcd, errstr, sizeof(errstr)); +- MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO +- ,_("Receive packet threw EAGAIN returning -2 code :%s"),errstr); ++ ++ while (retcd >= 0) { ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 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 { ++ if (ffmpeg_write_packet(ffmpeg) < 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 -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; + } + + return 0; +@@ -417,11 +436,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){ +@@ -430,6 +453,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -2; + } + ++ 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 +@@ -438,6 +470,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); + +@@ -463,6 +499,17 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.pts = ffmpeg->picture->pts; + ffmpeg->pkt.dts = ffmpeg->pkt.pts; + ++ 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; +@@ -1000,14 +1047,9 @@ static int ffmpeg_flush_codec(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 0; + } + +@@ -1016,21 +1058,9 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + if (retcd != -2){ + 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); +- } +- my_packet_unref(ffmpeg->pkt); +- +- if (retcd < 0) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error while writing video frame")); +- return -1; +- } + return retcd; + + } From ca1abef2446efc92bfaa99f0516449531ddabf02 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 29 Aug 2019 01:17:16 +1000 Subject: [PATCH 14/17] ffmpeg: make v4l2 buffer dequeue non-blocking (zero timeout) --- ...006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch index bd39b9587f..3be06d5586 100644 --- a/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch +++ b/package/ffmpeg/1006-avcodec-v4l2-add-timeout-when-dequeueing-buffers.patch @@ -15,7 +15,7 @@ index efcb0426e4..8f9420e28d 100644 * 2. an input buffer is ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 50); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 0); if (!avbuf) { if (ctx->done) return AVERROR_EOF; @@ -24,7 +24,7 @@ index efcb0426e4..8f9420e28d 100644 * 2. an input buffer ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, -1); -+ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 50); ++ avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? -1 : 0); if (!avbuf) { if (ctx->done) return AVERROR_EOF; From 87046d69096e4d8a894a15c8ec371bac44004f6a Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 4 Sep 2019 15:40:05 +1000 Subject: [PATCH 15/17] ffmpeg: upgrade to version 4.2 --- package/ffmpeg/ffmpeg.hash | 2 +- package/ffmpeg/ffmpeg.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/ffmpeg/ffmpeg.hash b/package/ffmpeg/ffmpeg.hash index f27eaa5706..1e03383055 100644 --- a/package/ffmpeg/ffmpeg.hash +++ b/package/ffmpeg/ffmpeg.hash @@ -1,5 +1,5 @@ # Locally calculated -sha256 f1f049a82fcfbf156564e73a3935d7e750891fab2abf302e735104fd4050a7e1 ffmpeg-4.1.4.tar.xz +sha256 023f10831a97ad93d798f53a3640e55cd564abfeba807ecbe8524dac4fedecd5 ffmpeg-4.2.tar.xz sha256 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643 COPYING.GPLv2 sha256 b634ab5640e258563c536e658cad87080553df6f34f62269a21d554844e58bfe COPYING.LGPLv2.1 sha256 73d99bc83313fff665b426d6672b4e0479102bc402fe22314ac9ce94a38aa5ff LICENSE.md diff --git a/package/ffmpeg/ffmpeg.mk b/package/ffmpeg/ffmpeg.mk index 349ed20822..89632ef282 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -4,7 +4,7 @@ # ################################################################################ -FFMPEG_VERSION = 4.1.4 +FFMPEG_VERSION = 4.2 FFMPEG_SOURCE = ffmpeg-$(FFMPEG_VERSION).tar.xz FFMPEG_SITE = http://ffmpeg.org/releases FFMPEG_INSTALL_STAGING = YES From 07e318b24f4c1d40ec78b581c6e78d1c69f97a4d Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 5 Sep 2019 14:31:27 +1000 Subject: [PATCH 16/17] ffmpeg: v4l2_m2m encoder: revert back to separate header mode --- ...se-joined-with-1st-frame-header-mode.patch | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch diff --git a/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch b/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch deleted file mode 100644 index 4aea0ede30..0000000000 --- a/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit e370306deb9c48f4daa4ae4d622a7bd8b3828bef -Author: Joo Aun Saw -Date: Mon Aug 19 15:20:52 2019 +1000 - - avcodec/v4l2_m2m_enc: use joined with 1st frame header mode - -diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c -index 354d78babb..32aaaf18fb 100644 ---- a/libavcodec/v4l2_m2m_enc.c -+++ b/libavcodec/v4l2_m2m_enc.c -@@ -174,7 +174,7 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) - v4l2_set_timeperframe(s, avctx->framerate.num, avctx->framerate.den); - - /* set ext ctrls */ -- v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode"); -+ v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_JOINED_WITH_1ST_FRAME), "header mode"); - /* enable bit rate control */ - if (avctx->bit_rate > 1) { - v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE) , 1, "rate control"); From 022ad4e92d24c371514d902b5737b618c0f72631 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 5 Sep 2019 14:32:36 +1000 Subject: [PATCH 17/17] motion: update patches to deal with v4l2m2m separate header mode --- package/motion/0002-enable-h264-v4l2m2m.patch | 168 +++++++++++++----- .../0003-ensure-first-frame-pts-zero.patch | 23 +++ .../0003-fix-h264-v4l2m2m-drain-error.patch | 35 ---- ...01-decouple-avcodec-send-and-receive.patch | 87 ++++++--- 4 files changed, 204 insertions(+), 109 deletions(-) create mode 100644 package/motion/0003-ensure-first-frame-pts-zero.patch delete mode 100644 package/motion/0003-fix-h264-v4l2m2m-drain-error.patch diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch index 416ab8d279..2a3423c916 100644 --- a/package/motion/0002-enable-h264-v4l2m2m.patch +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -1,14 +1,49 @@ -commit cbf86207346d9f1bc36005c2a6342bacf4bcc3e4 -Author: Joo Aun Saw -Date: Mon Aug 19 16:33:08 2019 +1000 - - support h264_v4l2m2m encoder - diff --git a/ffmpeg.c b/ffmpeg.c -index 3f731ca..beb87b1 100644 +index 3f731ca..7a42d24 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -555,7 +555,9 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ +@@ -179,6 +179,14 @@ int my_copy_packet(AVPacket *dest_pkt, AVPacket *src_pkt){ + #endif + } + /*********************************************/ ++void my_free_nal_info(struct ffmpeg *ffmpeg){ ++ if (ffmpeg->nal_info) { ++ free(ffmpeg->nal_info); ++ ffmpeg->nal_info = NULL; ++ ffmpeg->nal_info_len = 0; ++ } ++} ++/*********************************************/ + + /**************************************************************************** + **************************************************************************** +@@ -409,6 +417,25 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -1; + } + ++ if (ffmpeg->nal_info_separated) { ++ // h264_v4l2m2m has NAL units separated from the first frame, which makes ++ // some players very unhappy. ++ if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { ++ my_free_nal_info(ffmpeg); ++ ffmpeg->nal_info_len = ffmpeg->pkt.size; ++ ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); ++ if (ffmpeg->nal_info) ++ memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); ++ else ++ ffmpeg->nal_info_len = 0; ++ } else if (ffmpeg->nal_info) { ++ int old_size = ffmpeg->pkt.size; ++ av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); ++ memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); ++ memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); ++ my_free_nal_info(ffmpeg); ++ } ++ } + return 0; + + #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) +@@ -555,7 +582,9 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ ffmpeg->quality = 45; // default to 45% quality av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); @@ -19,7 +54,7 @@ index 3f731ca..beb87b1 100644 // H264 OMX encoder quality can only be controlled via bit_rate // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->quality) >> 7); -@@ -702,7 +708,10 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ +@@ -702,13 +731,20 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ ffmpeg->ctx_codec->height = ffmpeg->height; ffmpeg->ctx_codec->time_base.num = 1; ffmpeg->ctx_codec->time_base.den = ffmpeg->fps; @@ -31,12 +66,22 @@ index 3f731ca..beb87b1 100644 ffmpeg->ctx_codec->max_b_frames = 0; if (strcmp(ffmpeg->codec_name, "ffv1") == 0){ ffmpeg->ctx_codec->strict_std_compliance = -2; -@@ -768,6 +777,65 @@ static int ffmpeg_set_stream(struct ffmpeg *ffmpeg){ + ffmpeg->ctx_codec->level = 3; + } + ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_GLOBAL_HEADER; ++ // h264_v4l2m2m has NAL units separated from the first frame. We need to deal ++ // with it appriopriately later ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) ++ ffmpeg->nal_info_separated = 1; + + retcd = ffmpeg_set_quality(ffmpeg); + if (retcd < 0){ +@@ -768,8 +804,69 @@ static int ffmpeg_set_stream(struct ffmpeg *ffmpeg){ } + -+static int alloc_video_buffer(AVFrame *frame, int align) ++static int ffmpeg_alloc_video_buffer(AVFrame *frame, int align) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int ret, i, padded_height; @@ -73,12 +118,14 @@ index 3f731ca..beb87b1 100644 + frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding); + if (!frame->buf[0]) { + ret = AVERROR(ENOMEM); -+ goto fail; ++ av_frame_unref(frame); ++ return ret; + } + frame->buf[1] = av_buffer_alloc(ret + 4*plane_padding); + if (!frame->buf[1]) { + ret = AVERROR(ENOMEM); -+ goto fail; ++ av_frame_unref(frame); ++ return ret; + } + + frame->data[0] = frame->buf[0]->data; @@ -88,23 +135,27 @@ index 3f731ca..beb87b1 100644 + frame->extended_data = frame->data; + + return 0; -+fail: -+ av_frame_unref(frame); -+ return ret; +} + + static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ ++ int retcd; ++ char errstr[128]; ++ ffmpeg->picture = my_frame_alloc(); -@@ -789,6 +857,15 @@ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ + if (!ffmpeg->picture) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc frame")); +@@ -789,6 +886,17 @@ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ ffmpeg->picture->width = ffmpeg->ctx_codec->width; ffmpeg->picture->height = ffmpeg->ctx_codec->height; + // h264_v4l2m2m encoder expects video buffer to be allocated + if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { -+ if (alloc_video_buffer(ffmpeg->picture, 32)) { -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers")); ++ retcd = ffmpeg_alloc_video_buffer(ffmpeg->picture, 32); ++ if (retcd) { ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers %s"), errstr); + ffmpeg_free_context(ffmpeg); + return -1; + } @@ -113,45 +164,70 @@ index 3f731ca..beb87b1 100644 return 0; } -@@ -1365,9 +1442,38 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s +@@ -891,6 +999,12 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ + my_packet_unref(ffmpeg->pkt); + return -1; + } ++ // v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EOF ++ if ((ffmpeg->pkt.pts == 0) || (ffmpeg->pkt.size == 0)) { ++ recv_cd = AVERROR_EOF; ++ my_packet_unref(ffmpeg->pkt); ++ continue; ++ } + retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO +@@ -1339,6 +1453,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ + } + } + ffmpeg_free_context(ffmpeg); ++ my_free_nal_info(ffmpeg); + } + + #else +@@ -1365,9 +1480,28 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s } /* Setup pointers and line widths. */ - ffmpeg->picture->data[0] = image; - ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); - ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) / 4); -+ // Some encoders look for the image in ffmpeg->picture->buf -+ if (ffmpeg->picture->buf[0] == NULL) -+ ffmpeg->picture->data[0] = image; -+ else -+ memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); -+ -+ if (ffmpeg->picture->buf[1] == NULL) { -+ // assume YUV420P format -+ ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); -+ ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4); -+ } else { ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { ++ // assume NV21 format + int cr_len = ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4; -+ int cb_len = cr_len; + unsigned char *imagecr = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); + unsigned char *imagecb = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) + cr_len; -+ if (ffmpeg->ctx_codec->pix_fmt == AV_PIX_FMT_NV21) { -+ int x; -+ int y; -+ for (y = 0; y < ffmpeg->ctx_codec->height; y++) { -+ for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) { -+ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imagecb; -+ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *imagecr; -+ imagecb++; -+ imagecr++; -+ } ++ int x; ++ int y; ++ memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ for (y = 0; y < ffmpeg->ctx_codec->height; y++) { ++ for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) { ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imagecb; ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *imagecr; ++ imagecb++; ++ imagecr++; + } -+ } else { -+ // assume YUV420P format -+ memcpy(&ffmpeg->picture->data[1][0], imagecr, cr_len); -+ memcpy(&ffmpeg->picture->data[1][cr_len], imagecb, cb_len); + } ++ } else { ++ // assume YUV420P format ++ ffmpeg->picture->data[0] = image; ++ ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) / 4); + } ffmpeg->gop_cnt ++; if (ffmpeg->gop_cnt == ffmpeg->ctx_codec->gop_size ){ +diff --git a/ffmpeg.h b/ffmpeg.h +index ca77430..c4ae7bb 100644 +--- a/ffmpeg.h ++++ b/ffmpeg.h +@@ -61,6 +61,9 @@ struct ffmpeg { + int high_resolution; + int motion_images; + int passthrough; ++ int nal_info_separated; ++ char *nal_info; ++ int nal_info_len; + }; + #else + struct ffmpeg { diff --git a/package/motion/0003-ensure-first-frame-pts-zero.patch b/package/motion/0003-ensure-first-frame-pts-zero.patch new file mode 100644 index 0000000000..56b0d6c19c --- /dev/null +++ b/package/motion/0003-ensure-first-frame-pts-zero.patch @@ -0,0 +1,23 @@ +commit 0cd12918f93fc6559dad56d176a60ddc3f0844d6 +Author: Joo Aun Saw +Date: Thu Sep 5 14:20:07 2019 +1000 + + ffmpeg: ensure first frame PTS is zero + +diff --git a/ffmpeg.c b/ffmpeg.c +index 7a42d24..665aa00 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -512,7 +512,11 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg_reset_movie_start_time(ffmpeg, tv1); + pts_interval = 0; + } +- ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; ++ if (ffmpeg->last_pts < 0) { ++ // This is the very first frame, ensure PTS is zero ++ ffmpeg->picture->pts = 0; ++ } else ++ ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; + + if (ffmpeg->test_mode == TRUE){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO diff --git a/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch b/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch deleted file mode 100644 index 0937f8f9a6..0000000000 --- a/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch +++ /dev/null @@ -1,35 +0,0 @@ -commit d1aad9ec2b37560ddf2b2a362e30882adce8fb94 -Author: Joo Aun Saw -Date: Mon Aug 19 16:36:30 2019 +1000 - - fix h264_v4l2m2m encoder draining error - - When h264_v4l2m2m encoder is drained, it sets packet pts and size to - zero rather than returning AVERROR_EOF. - -diff --git a/ffmpeg.c b/ffmpeg.c -index beb87b1..a3a8701 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -968,11 +968,16 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ - my_packet_unref(ffmpeg->pkt); - return -1; - } -- retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); -- if (retcd < 0) { -- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO -- ,_("Error writing draining video frame")); -- return -1; -+ // v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EOF -+ if ((ffmpeg->pkt.pts > 0) && (ffmpeg->pkt.size > 0)) { -+ retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); -+ if (retcd < 0) { -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO -+ ,_("Error writing draining video frame")); -+ return -1; -+ } -+ } else { -+ recv_cd = AVERROR_EOF; - } - } - my_packet_unref(ffmpeg->pkt); diff --git a/package/motion/1001-decouple-avcodec-send-and-receive.patch b/package/motion/1001-decouple-avcodec-send-and-receive.patch index 54e9c4a493..cf35ada2e0 100644 --- a/package/motion/1001-decouple-avcodec-send-and-receive.patch +++ b/package/motion/1001-decouple-avcodec-send-and-receive.patch @@ -1,19 +1,12 @@ -commit b9b521dc5d6179e8570d826e00728130144e3902 -Author: Joo Aun Saw -Date: Tue Aug 27 01:09:43 2019 +1000 - - ffmpeg: decouple avcodec send and receive - diff --git a/ffmpeg.c b/ffmpeg.c -index 6b5459d..18b2894 100644 +index 665aa00..1246fdc 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -378,6 +378,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ +@@ -386,6 +386,14 @@ 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 { @@ -24,7 +17,7 @@ index 6b5459d..18b2894 100644 static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) -@@ -392,21 +401,31 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -400,41 +408,49 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ,_("Error sending frame for encoding:%s"),errstr); return -1; } @@ -34,7 +27,34 @@ index 6b5459d..18b2894 100644 - av_strerror(retcd, errstr, sizeof(errstr)); - MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO - ,_("Receive packet threw EAGAIN returning -2 code :%s"),errstr); -+ +- 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->nal_info_separated) { +- // h264_v4l2m2m has NAL units separated from the first frame, which makes +- // some players very unhappy. +- if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { +- my_free_nal_info(ffmpeg); +- ffmpeg->nal_info_len = ffmpeg->pkt.size; +- ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); +- if (ffmpeg->nal_info) +- memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); +- else +- ffmpeg->nal_info_len = 0; +- } else if (ffmpeg->nal_info) { +- int old_size = ffmpeg->pkt.size; +- av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); +- memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); +- memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); +- my_free_nal_info(ffmpeg); + while (retcd >= 0) { + av_init_packet(&ffmpeg->pkt); + ffmpeg->pkt.data = NULL; @@ -44,13 +64,32 @@ index 6b5459d..18b2894 100644 + //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 { ++ if (ffmpeg->nal_info_separated) { ++ // h264_v4l2m2m has NAL units separated from the first frame, which makes ++ // some players very unhappy. ++ if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { ++ my_free_nal_info(ffmpeg); ++ ffmpeg->nal_info_len = ffmpeg->pkt.size; ++ ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); ++ if (ffmpeg->nal_info) ++ memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); ++ else ++ ffmpeg->nal_info_len = 0; ++ } else if (ffmpeg->nal_info) { ++ int old_size = ffmpeg->pkt.size; ++ av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); ++ memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); ++ memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); ++ my_free_nal_info(ffmpeg); ++ } ++ } + if (ffmpeg_write_packet(ffmpeg) < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); @@ -58,19 +97,11 @@ index 6b5459d..18b2894 100644 + return -1; + } + } - 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; ++ my_packet_unref(ffmpeg->pkt); } - return 0; -@@ -417,11 +436,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + +@@ -444,11 +460,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ char errstr[128]; int got_packet_ptr; @@ -87,7 +118,7 @@ index 6b5459d..18b2894 100644 return -1; } if (got_packet_ptr == 0){ -@@ -430,6 +453,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -457,6 +477,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ return -2; } @@ -103,7 +134,7 @@ index 6b5459d..18b2894 100644 return 0; #else -@@ -438,6 +470,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -465,6 +494,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ uint8_t *video_outbuf; int video_outbuf_size; @@ -114,7 +145,7 @@ index 6b5459d..18b2894 100644 video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; video_outbuf = mymalloc(video_outbuf_size); -@@ -463,6 +499,17 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -490,6 +523,17 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ffmpeg->pkt.pts = ffmpeg->picture->pts; ffmpeg->pkt.dts = ffmpeg->pkt.pts; @@ -132,7 +163,7 @@ index 6b5459d..18b2894 100644 free(video_outbuf); return 0; -@@ -1000,14 +1047,9 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ +@@ -1034,14 +1078,9 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ int retcd; @@ -147,7 +178,7 @@ index 6b5459d..18b2894 100644 return 0; } -@@ -1016,21 +1058,9 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +@@ -1050,21 +1089,9 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ if (retcd != -2){ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error while encoding picture")); }