diff --git a/configs/odroidxu4_defconfig b/configs/odroidxu4_defconfig index d03edfdf9f..2b0a175406 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" 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 - 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/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..3be06d5586 --- /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 : 0); + 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 : 0); + if (!avbuf) { + if (ctx->done) + return AVERROR_EOF; 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); + diff --git a/package/ffmpeg/ffmpeg.hash b/package/ffmpeg/ffmpeg.hash index e00c4ec56c..1e03383055 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 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 b86d465df8..89632ef282 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -4,7 +4,7 @@ # ################################################################################ -FFMPEG_VERSION = 3.4.5 +FFMPEG_VERSION = 4.2 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 diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch new file mode 100644 index 0000000000..2a3423c916 --- /dev/null +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -0,0 +1,233 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 3f731ca..7a42d24 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -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); +- 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); +@@ -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; +- 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; + 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 ffmpeg_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); ++ av_frame_unref(frame); ++ return ret; ++ } ++ frame->buf[1] = av_buffer_alloc(ret + 4*plane_padding); ++ if (!frame->buf[1]) { ++ ret = AVERROR(ENOMEM); ++ av_frame_unref(frame); ++ return ret; ++ } ++ ++ 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; ++} ++ ++ + static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ + ++ int retcd; ++ char errstr[128]; ++ + ffmpeg->picture = my_frame_alloc(); + 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) { ++ 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; ++ } ++ } ++ + return 0; + + } +@@ -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); ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { ++ // assume NV21 format ++ int cr_len = ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4; ++ 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; ++ 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 ++ 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/1001-decouple-avcodec-send-and-receive.patch b/package/motion/1001-decouple-avcodec-send-and-receive.patch new file mode 100644 index 0000000000..cf35ada2e0 --- /dev/null +++ b/package/motion/1001-decouple-avcodec-send-and-receive.patch @@ -0,0 +1,202 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 665aa00..1246fdc 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -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 { ++ 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)) +@@ -400,41 +408,49 @@ 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); +- 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; ++ 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->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); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ } ++ my_packet_unref(ffmpeg->pkt); + } + return 0; + +@@ -444,11 +460,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){ +@@ -457,6 +477,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 +@@ -465,6 +494,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); + +@@ -490,6 +523,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; +@@ -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; + +- 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; + } + +@@ -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")); + } +- 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; + + }