diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0001-vf_bwdif-Add-capability-to-deinterlace-NV12.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0001-vf_bwdif-Add-capability-to-deinterlace-NV12.patch new file mode 100644 index 0000000000..4b22400c0a --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0001-vf_bwdif-Add-capability-to-deinterlace-NV12.patch @@ -0,0 +1,62 @@ +From 162a9ac64b7babb4e831df86f6ed0efdfe84204e Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Fri, 12 Jan 2024 15:17:43 +0000 +Subject: [PATCH 01/14] vf_bwdif: Add capability to deinterlace NV12 + +As bwdif takes no account of horizontally adjacent pixels the same +code can be used on planes that have multiple components as is used +on single component planes. Update the filtering code to cope with +multi-component planes and add NV12 to the list of supported formats. + +Signed-off-by: John Cox +--- + libavfilter/vf_bwdif.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c +index 9847d38b6a..4d69b3039d 100644 +--- a/libavfilter/vf_bwdif.c ++++ b/libavfilter/vf_bwdif.c +@@ -302,19 +302,28 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic, + YADIFContext *yadif = &bwdif->yadif; + ThreadData td = { .frame = dstpic, .parity = parity, .tff = tff }; + int i; ++ int last_plane = -1; + + for (i = 0; i < yadif->csp->nb_components; i++) { + int w = dstpic->width; + int h = dstpic->height; ++ const AVComponentDescriptor * const comp = yadif->csp->comp + i; ++ ++ // If the last plane was the same as this plane assume we've dealt ++ // with all the pels already ++ if (last_plane == comp->plane) ++ continue; ++ last_plane = comp->plane; + + if (i == 1 || i == 2) { + w = AV_CEIL_RSHIFT(w, yadif->csp->log2_chroma_w); + h = AV_CEIL_RSHIFT(h, yadif->csp->log2_chroma_h); + } + +- td.w = w; +- td.h = h; +- td.plane = i; ++ // comp step is in bytes but td.w is in pels ++ td.w = w * comp->step / ((comp->depth + 7) / 8); ++ td.h = h; ++ td.plane = comp->plane; + + ff_filter_execute(ctx, filter_slice, &td, NULL, + FFMIN((h+3)/4, ff_filter_get_nb_threads(ctx))); +@@ -350,6 +359,7 @@ static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, ++ AV_PIX_FMT_NV12, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP16, +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0002-v4l2_m2m_dec-Try-to-accomodate-ffmpegs-ideas-about-d.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0002-v4l2_m2m_dec-Try-to-accomodate-ffmpegs-ideas-about-d.patch new file mode 100644 index 0000000000..8b8e711704 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0002-v4l2_m2m_dec-Try-to-accomodate-ffmpegs-ideas-about-d.patch @@ -0,0 +1,65 @@ +From 4960acb627d736421251500b3e4e0e88d3b12cd1 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Fri, 12 Jan 2024 16:46:27 +0000 +Subject: [PATCH 02/14] v4l2_m2m_dec: Try to accomodate ffmpegs ideas about + default s/w fmts + +--- + libavcodec/v4l2_m2m_dec.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index f67dd23ba1..3883223079 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -1079,7 +1079,6 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s) + unsigned int fmts_n; + uint32_t *fmts = ff_v4l2_context_enum_drm_formats(&s->capture, &fmts_n); + enum AVPixelFormat *fmts2 = NULL; +- enum AVPixelFormat t; + enum AVPixelFormat gf_pix_fmt; + unsigned int i; + unsigned int n = 0; +@@ -1089,7 +1088,7 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s) + if (!fmts) + return AVERROR(ENOENT); + +- if ((fmts2 = av_malloc(sizeof(*fmts2) * (fmts_n + 2))) == NULL) { ++ if ((fmts2 = av_malloc(sizeof(*fmts2) * (fmts_n + 3))) == NULL) { + rv = AVERROR(ENOMEM); + goto error; + } +@@ -1110,17 +1109,25 @@ choose_capture_format(AVCodecContext * const avctx, V4L2m2mContext * const s) + pref_n = n; + fmts2[n++] = f; + } +- fmts2[n] = AV_PIX_FMT_NONE; + + if (n < 2) { + av_log(avctx, AV_LOG_DEBUG, "%s: No usable formats found\n", __func__); + goto error; + } + +- // Put preferred s/w format at the end - ff_get_format will put it in sw_pix_fmt +- t = fmts2[n - 1]; +- fmts2[n - 1] = fmts2[pref_n]; +- fmts2[pref_n] = t; ++ if (n != 2) { ++ // ffmpeg.c really only expects one s/w format. It thinks that the ++ // last format in the list is the s/w format of the h/w format but ++ // also chooses the first non-h/w format as the preferred s/w format. ++ // The only way of reconciling this is to dup our preferred format into ++ // both last & first place :-( ++ const enum AVPixelFormat t = fmts2[pref_n]; ++ fmts2[pref_n] = fmts2[1]; ++ fmts2[1] = t; ++ fmts2[n++] = t; ++ } ++ ++ fmts2[n] = AV_PIX_FMT_NONE; + + gf_pix_fmt = ff_get_format(avctx, fmts2); + av_log(avctx, AV_LOG_DEBUG, "avctx requested=%d (%s) %dx%d; get_format requested=%d (%s)\n", +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0003-v4l2_m2m_dec-Fix-cma-allocated-s-w-output.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0003-v4l2_m2m_dec-Fix-cma-allocated-s-w-output.patch new file mode 100644 index 0000000000..f4cf5b2724 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0003-v4l2_m2m_dec-Fix-cma-allocated-s-w-output.patch @@ -0,0 +1,92 @@ +From 80f74137438df2cfe911907242ec96593642f64b Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Thu, 18 Jan 2024 15:57:30 +0000 +Subject: [PATCH 03/14] v4l2_m2m_dec: Fix cma allocated s/w output + +--- + libavcodec/v4l2_buffers.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index e412636a7a..b3ef74bcd4 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -486,6 +486,11 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data) + // Buffer still attached to context + V4L2m2mContext *s = buf_to_m2mctx(avbuf); + ++ if (!s->output_drm && avbuf->dmabuf[0] != NULL) { ++ for (unsigned int i = 0; i != avbuf->num_planes; ++i) ++ dmabuf_read_end(avbuf->dmabuf[i]); ++ } ++ + ff_mutex_lock(&ctx->lock); + + ff_v4l2_buffer_set_avail(avbuf); +@@ -533,6 +538,9 @@ static int v4l2_buffer_export_drm(V4L2Buffer* avbuf) + avbuf->buf.m.planes[i].m.fd = dma_fd; + else + avbuf->buf.m.fd = dma_fd; ++ ++ if (!s->output_drm) ++ avbuf->plane_info[i].mm_addr = dmabuf_map(avbuf->dmabuf[i]); + } + else { + struct v4l2_exportbuffer expbuf; +@@ -647,6 +655,11 @@ static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) + break; + } + ++ if (avbuf->dmabuf[0] != NULL) { ++ for (unsigned int i = 0; i != avbuf->num_planes; ++i) ++ dmabuf_read_start(avbuf->dmabuf[i]); ++ } ++ + return 0; + } + +@@ -947,6 +960,7 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct + V4L2Buffer * const avbuf = av_mallocz(sizeof(*avbuf)); + AVBufferRef * bufref; + V4L2m2mContext * const s = ctx_to_m2mctx(ctx); ++ int want_mmap; + + *pbufref = NULL; + if (avbuf == NULL) +@@ -988,10 +1002,10 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct + } else + avbuf->num_planes = 1; + +- for (i = 0; i < avbuf->num_planes; i++) { +- const int want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP && +- (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm); ++ want_mmap = avbuf->buf.memory == V4L2_MEMORY_MMAP && ++ (V4L2_TYPE_IS_OUTPUT(ctx->type) || !buf_to_m2mctx(avbuf)->output_drm); + ++ for (i = 0; i < avbuf->num_planes; i++) { + avbuf->plane_info[i].bytesperline = V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? + ctx->format.fmt.pix_mp.plane_fmt[i].bytesperline : + ctx->format.fmt.pix.bytesperline; +@@ -1032,13 +1046,12 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct + avbuf->buf.length = avbuf->planes[0].length; + } + +- if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) { +- if (s->output_drm) { +- ret = v4l2_buffer_export_drm(avbuf); +- if (ret) { +- av_log(logger(avbuf), AV_LOG_ERROR, "Failed to get exported drm handles\n"); +- goto fail; +- } ++ if (!want_mmap) { ++ // export_drm does dmabuf alloc if we aren't using v4l2 alloc ++ ret = v4l2_buffer_export_drm(avbuf); ++ if (ret) { ++ av_log(logger(avbuf), AV_LOG_ERROR, "Failed to get exported drm handles\n"); ++ goto fail; + } + } + +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0004-v4l2_req-Fix-media-pool-delete-race.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0004-v4l2_req-Fix-media-pool-delete-race.patch new file mode 100644 index 0000000000..a9abd0f59a --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0004-v4l2_req-Fix-media-pool-delete-race.patch @@ -0,0 +1,109 @@ +From c1328b956e9856210b1f2bc20c20fd152c309123 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Mon, 29 Jan 2024 15:12:34 +0000 +Subject: [PATCH 04/14] v4l2_req: Fix media pool delete race + +fds & polltasks associated with media fds that are still in flight are +not freed on delete but the main pool is leading to use after free when +they finally do complete. Stop scanning the free chain on delete and +simply delete everything, in-flight or not. This requires changing alloc +as the buffers weren't previously tracked in-flight. +--- + libavcodec/v4l2_req_media.c | 38 ++++++++++++++++++++----------------- + 1 file changed, 21 insertions(+), 17 deletions(-) + +diff --git a/libavcodec/v4l2_req_media.c b/libavcodec/v4l2_req_media.c +index 0394bb2b23..c94cc5b0f6 100644 +--- a/libavcodec/v4l2_req_media.c ++++ b/libavcodec/v4l2_req_media.c +@@ -86,6 +86,8 @@ struct media_pool { + int fd; + sem_t sem; + pthread_mutex_t lock; ++ unsigned int pool_n; ++ struct media_request * pool_reqs; + struct media_request * free_reqs; + struct pollqueue * pq; + }; +@@ -251,18 +253,17 @@ int media_request_abort(struct media_request ** const preq) + return 0; + } + +-static void delete_req_chain(struct media_request * const chain) ++static void free_req_pool(struct media_request * const pool, const unsigned int n) + { +- struct media_request * next = chain; +- while (next) { +- struct media_request * const req = next; +- next = req->next; ++ unsigned int i; ++ for (i = 0; i != n; ++i) { ++ struct media_request * const req = pool + i; + if (req->pt) + polltask_delete(&req->pt); + if (req->fd != -1) + close(req->fd); +- free(req); + } ++ free(pool); + } + + struct media_pool * media_pool_new(const char * const media_path, +@@ -283,17 +284,16 @@ struct media_pool * media_pool_new(const char * const media_path, + goto fail1; + } + ++ if ((mp->pool_reqs = calloc(n, sizeof(*mp->pool_reqs))) == NULL) ++ goto fail3; ++ mp->pool_n = n; + for (i = 0; i != n; ++i) { +- struct media_request * req = malloc(sizeof(*req)); +- if (!req) +- goto fail4; ++ mp->pool_reqs[i].mp = mp; ++ mp->pool_reqs[i].fd = -1; ++ } + +- *req = (struct media_request){ +- .next = mp->free_reqs, +- .mp = mp, +- .fd = -1 +- }; +- mp->free_reqs = req; ++ for (i = 0; i != n; ++i) { ++ struct media_request * const req = mp->pool_reqs + i; + + if (ioctl(mp->fd, MEDIA_IOC_REQUEST_ALLOC, &req->fd) == -1) { + request_log("Failed to alloc request %d: %s\n", i, strerror(errno)); +@@ -303,6 +303,9 @@ struct media_pool * media_pool_new(const char * const media_path, + req->pt = polltask_new(pq, req->fd, POLLPRI, media_request_done, req); + if (!req->pt) + goto fail4; ++ ++ req->next = mp->free_reqs, ++ mp->free_reqs = req; + } + + sem_init(&mp->sem, 0, n); +@@ -310,7 +313,8 @@ struct media_pool * media_pool_new(const char * const media_path, + return mp; + + fail4: +- delete_req_chain(mp->free_reqs); ++ free_req_pool(mp->pool_reqs, mp->pool_n); ++fail3: + close(mp->fd); + pthread_mutex_destroy(&mp->lock); + fail1: +@@ -327,7 +331,7 @@ void media_pool_delete(struct media_pool ** pMp) + return; + *pMp = NULL; + +- delete_req_chain(mp->free_reqs); ++ free_req_pool(mp->pool_reqs, mp->pool_n); + close(mp->fd); + sem_destroy(&mp->sem); + pthread_mutex_destroy(&mp->lock); +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0005-drm_vout-Fix-connector-etc.-desc-memory-leak.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0005-drm_vout-Fix-connector-etc.-desc-memory-leak.patch new file mode 100644 index 0000000000..857e0dfd53 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0005-drm_vout-Fix-connector-etc.-desc-memory-leak.patch @@ -0,0 +1,30 @@ +From 613e5cbb5e0a7626377876e9a441c614afe1e25e Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Tue, 30 Jan 2024 14:24:59 +0000 +Subject: [PATCH 05/14] drm_vout: Fix connector etc. desc memory leak + +--- + libavdevice/drm_vout.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/libavdevice/drm_vout.c b/libavdevice/drm_vout.c +index 491e1dc608..275748abdc 100644 +--- a/libavdevice/drm_vout.c ++++ b/libavdevice/drm_vout.c +@@ -501,6 +501,13 @@ static int find_crtc(struct AVFormatContext * const avctx, int drmfd, struct drm + crtc ? crtc->height : 0, + (s->conId == (int)con->connector_id ? + " (chosen)" : "")); ++ ++ if (crtc) ++ drmModeFreeCrtc(crtc); ++ if (enc) ++ drmModeFreeEncoder(enc); ++ if (con) ++ drmModeFreeConnector(con); + } + + if (!s->conId) { +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0006-conf_native-Add-tsan-option.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0006-conf_native-Add-tsan-option.patch new file mode 100644 index 0000000000..9b23f933a2 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0006-conf_native-Add-tsan-option.patch @@ -0,0 +1,58 @@ +From f1868ad7d598cf4f194680a5e8d116744d8227cc Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Tue, 30 Jan 2024 16:20:53 +0000 +Subject: [PATCH 06/14] conf_native: Add --tsan option + +--- + pi-util/conf_native.sh | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/pi-util/conf_native.sh b/pi-util/conf_native.sh +index f0ed159594..0dbaa53e97 100755 +--- a/pi-util/conf_native.sh ++++ b/pi-util/conf_native.sh +@@ -10,6 +10,8 @@ RPI_KEEPS="" + NOSHARED= + MMAL= + USR_PREFIX= ++TOOLCHAIN= ++R=rel + + while [ "$1" != "" ] ; do + case $1 in +@@ -22,6 +24,10 @@ while [ "$1" != "" ] ; do + --usr) + USR_PREFIX=/usr + ;; ++ --tsan) ++ TOOLCHAIN="--toolchain=gcc-tsan" ++ R=tsan ++ ;; + *) + echo "Usage $0: [--noshared] [--mmal] [--usr]" + echo " noshared Build static libs and executable - good for testing" +@@ -82,11 +88,11 @@ V=`cat RELEASE` + SHARED_LIBS="--enable-shared" + if [ $NOSHARED ]; then + SHARED_LIBS="--disable-shared" +- OUT=$BUILDBASE/$B-$C-$V-static-rel ++ OUT=$BUILDBASE/$B-$C-$V-static-$R + echo Static libs + else + echo Shared libs +- OUT=$BUILDBASE/$B-$C-$V-shared-rel ++ OUT=$BUILDBASE/$B-$C-$V-shared-$R + fi + + if [ ! $USR_PREFIX ]; then +@@ -106,6 +112,7 @@ $FFSRC/configure \ + --libdir=$LIB_PREFIX\ + --incdir=$INC_PREFIX\ + $MCOPTS\ ++ $TOOLCHAIN\ + --disable-stripping\ + --disable-thumb\ + --enable-sand\ +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0007-v4l2_m2m-Rework-use-of-ctx-lock-to-avoid-use-while-u.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0007-v4l2_m2m-Rework-use-of-ctx-lock-to-avoid-use-while-u.patch new file mode 100644 index 0000000000..ea6361b024 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0007-v4l2_m2m-Rework-use-of-ctx-lock-to-avoid-use-while-u.patch @@ -0,0 +1,166 @@ +From 4f458f6ef9d74a44029dab3c0416f630c96a968b Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Tue, 30 Jan 2024 16:25:53 +0000 +Subject: [PATCH 07/14] v4l2_m2m: Rework use of ctx->lock to avoid use while + uninit + +--- + libavcodec/v4l2_buffers.c | 9 ++-- + libavcodec/v4l2_context.c | 86 +++++++++++++++++++++++++++------------ + 2 files changed, 63 insertions(+), 32 deletions(-) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index b3ef74bcd4..e844a1a0b6 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -484,7 +484,7 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data) + + if (ctx != NULL) { + // Buffer still attached to context +- V4L2m2mContext *s = buf_to_m2mctx(avbuf); ++ V4L2m2mContext * const s = ctx_to_m2mctx(ctx); + + if (!s->output_drm && avbuf->dmabuf[0] != NULL) { + for (unsigned int i = 0; i != avbuf->num_planes; ++i) +@@ -494,15 +494,14 @@ static void v4l2_free_bufref(void *opaque, uint8_t *data) + ff_mutex_lock(&ctx->lock); + + ff_v4l2_buffer_set_avail(avbuf); ++ avbuf->buf.timestamp.tv_sec = 0; ++ avbuf->buf.timestamp.tv_usec = 0; + +- if (s->draining && V4L2_TYPE_IS_OUTPUT(ctx->type)) { ++ if (V4L2_TYPE_IS_OUTPUT(ctx->type)) { + av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer avail\n", ctx->name); +- /* no need to queue more buffers to the driver */ + } + else if (ctx->streamon) { + av_log(logger(avbuf), AV_LOG_DEBUG, "%s: Buffer requeue\n", ctx->name); +- avbuf->buf.timestamp.tv_sec = 0; +- avbuf->buf.timestamp.tv_usec = 0; + ff_v4l2_buffer_enqueue(avbuf); // will set to IN_DRIVER + } + else { +diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c +index a01a105892..0d61a432c3 100644 +--- a/libavcodec/v4l2_context.c ++++ b/libavcodec/v4l2_context.c +@@ -906,56 +906,88 @@ static int stuff_all_buffers(AVCodecContext * avctx, V4L2Context* ctx) + } + } + ++ ff_mutex_lock(&ctx->lock); + for (i = 0; i < ctx->num_buffers; ++i) { + struct V4L2Buffer * const buf = (struct V4L2Buffer *)ctx->bufrefs[i]->data; + if (buf->status == V4L2BUF_AVAILABLE) { + rv = ff_v4l2_buffer_enqueue(buf); + if (rv < 0) +- return rv; ++ break; + } + } +- return 0; ++ ff_mutex_unlock(&ctx->lock); ++ return rv; + } + +-int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) ++static int set_streamon(AVCodecContext * const avctx, V4L2Context*const ctx) + { + int type = ctx->type; + int ret = 0; +- AVCodecContext * const avctx = logger(ctx); ++ ++ if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) ++ stuff_all_buffers(avctx, ctx); ++ ++ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMON, &type) < 0) { ++ ret = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name, ++ av_err2str(ret)); ++ return ret; ++ } ++ ++ ctx->first_buf = 1; ++ ctx->streamon = 1; ++ ctx->flag_last = 0; ++ av_log(avctx, AV_LOG_DEBUG, "%s set status ON OK\n", ctx->name); ++ return ret; ++} ++ ++static int set_streamoff(AVCodecContext * const avctx, V4L2Context*const ctx) ++{ ++ int type = ctx->type; ++ int ret = 0; ++ const int has_bufs = ctx_buffers_alloced(ctx); + + // Avoid doing anything if there is nothing we can do +- if (cmd == VIDIOC_STREAMOFF && !ctx_buffers_alloced(ctx) && !ctx->streamon) ++ if (!has_bufs && !ctx->streamon) + return 0; + +- ff_mutex_lock(&ctx->lock); +- +- if (cmd == VIDIOC_STREAMON && !V4L2_TYPE_IS_OUTPUT(ctx->type)) +- stuff_all_buffers(avctx, ctx); ++ if (has_bufs) ++ ff_mutex_lock(&ctx->lock); + +- if (ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type) < 0) { +- const int err = errno; +- av_log(avctx, AV_LOG_ERROR, "%s set status %d (%s) failed: err=%d\n", ctx->name, +- cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF", err); +- ret = AVERROR(err); ++ if (ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_STREAMOFF, &type) < 0) { ++ ret = AVERROR(errno); ++ av_log(avctx, AV_LOG_ERROR, "%s set status ON failed: err=%s\n", ctx->name, ++ av_err2str(ret)); + } +- else +- { +- if (cmd == VIDIOC_STREAMOFF) +- flush_all_buffers_status(ctx); +- else +- ctx->first_buf = 1; ++ else { ++ flush_all_buffers_status(ctx); + +- ctx->streamon = (cmd == VIDIOC_STREAMON); +- av_log(avctx, AV_LOG_DEBUG, "%s set status %d (%s) OK\n", ctx->name, +- cmd, (cmd == VIDIOC_STREAMON) ? "ON" : "OFF"); ++ ctx->streamon = 0; ++ ctx->flag_last = 0; ++ ++ av_log(avctx, AV_LOG_DEBUG, "%s set status OFF OK\n", ctx->name); + } + +- // Both stream off & on effectively clear flag_last +- ctx->flag_last = 0; ++ if (has_bufs) ++ ff_mutex_unlock(&ctx->lock); ++ return ret; ++} + +- ff_mutex_unlock(&ctx->lock); + +- return ret; ++int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) ++{ ++ AVCodecContext * const avctx = logger(ctx); ++ ++ switch (cmd) { ++ case VIDIOC_STREAMOFF: ++ return set_streamoff(avctx, ctx); ++ case VIDIOC_STREAMON: ++ return set_streamon(avctx, ctx); ++ default: ++ av_log(avctx, AV_LOG_ERROR, "%s: Unexpected cmd: %d\n", __func__, cmd); ++ break; ++ } ++ return AVERROR_BUG; + } + + int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0008-matroskaenc-Fix-H264-delayed-extradata-creation.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0008-matroskaenc-Fix-H264-delayed-extradata-creation.patch new file mode 100644 index 0000000000..48a551f2e0 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0008-matroskaenc-Fix-H264-delayed-extradata-creation.patch @@ -0,0 +1,25 @@ +From e00b19de388fec567e37c10edeafa646d322afa6 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Thu, 1 Feb 2024 18:11:06 +0000 +Subject: [PATCH 08/14] matroskaenc: Fix H264 delayed extradata creation + +--- + libavformat/matroskaenc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c +index 61e4c976ef..a6a00f03e7 100644 +--- a/libavformat/matroskaenc.c ++++ b/libavformat/matroskaenc.c +@@ -1125,7 +1125,7 @@ static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn + case AV_CODEC_ID_WAVPACK: + return put_wv_codecpriv(dyn_cp, extradata, extradata_size); + case AV_CODEC_ID_H264: +- if (par->extradata_size) ++ if (extradata_size) + return ff_isom_write_avcc(dyn_cp, extradata, + extradata_size); + else +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0009-matroskaenc-Assume-H264-is-Annex-B-if-no-extradata.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0009-matroskaenc-Assume-H264-is-Annex-B-if-no-extradata.patch new file mode 100644 index 0000000000..9366384df9 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0009-matroskaenc-Assume-H264-is-Annex-B-if-no-extradata.patch @@ -0,0 +1,34 @@ +From 97c735a3fc0976aa50d819a2f397e9467228722d Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Thu, 1 Feb 2024 18:12:38 +0000 +Subject: [PATCH 09/14] matroskaenc: Assume H264 is Annex B if no extradata + +--- + libavformat/matroskaenc.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c +index a6a00f03e7..131ad31d1b 100644 +--- a/libavformat/matroskaenc.c ++++ b/libavformat/matroskaenc.c +@@ -3194,9 +3194,15 @@ static int mkv_init(struct AVFormatContext *s) + track->reformat = mkv_reformat_wavpack; + break; + case AV_CODEC_ID_H264: ++ // Default to reformat if no extradata as the only current ++ // encoder which does this is v4l2m2m which needs reformat ++ if (par->extradata_size == 0 || ++ (par->extradata_size > 3 && ++ (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))) ++ track->reformat = mkv_reformat_h2645; ++ break; + case AV_CODEC_ID_HEVC: +- if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 || +- par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) && ++ if (par->extradata_size > 6 && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) + track->reformat = mkv_reformat_h2645; + break; +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0010-aarch64-rgb2rgb-Change-incorrect-SXTX-to-stxw.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0010-aarch64-rgb2rgb-Change-incorrect-SXTX-to-stxw.patch new file mode 100644 index 0000000000..4f219d38c0 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0010-aarch64-rgb2rgb-Change-incorrect-SXTX-to-stxw.patch @@ -0,0 +1,42 @@ +From 47212b4641888cbf131cbc2f9da58af68e4c92e5 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Fri, 16 Feb 2024 11:50:56 +0000 +Subject: [PATCH 10/14] aarch64/rgb2rgb: Change incorrect SXTX to stxw + +--- + libswscale/aarch64/rgb2rgb_neon.S | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/libswscale/aarch64/rgb2rgb_neon.S b/libswscale/aarch64/rgb2rgb_neon.S +index 0956800b41..38f83a1b78 100644 +--- a/libswscale/aarch64/rgb2rgb_neon.S ++++ b/libswscale/aarch64/rgb2rgb_neon.S +@@ -338,8 +338,8 @@ function ff_bgr24toyv12_aarch64, export=1 + b.eq 90f + + subs w9, w4, #0 +- add x0, x0, w14, SXTX +- add x1, x1, w6, SXTX ++ add x0, x0, w14, sxtw ++ add x1, x1, w6, sxtw + mov x10, x0 + mov x11, x1 + b.lt 12f +@@ -424,10 +424,10 @@ function ff_bgr24toyv12_aarch64, export=1 + + // ------------------- Loop to start + +- add x0, x0, w14, SXTX +- add x1, x1, w6, SXTX +- add x2, x2, w7, SXTX +- add x3, x3, w7, SXTX ++ add x0, x0, w14, sxtw ++ add x1, x1, w6, sxtw ++ add x2, x2, w7, sxtw ++ add x3, x3, w7, sxtw + subs w5, w5, #1 + b.gt 11b + 90: +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0011-aarch64-rpi_sand-Fix-building-under-Clang-LLVM.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0011-aarch64-rpi_sand-Fix-building-under-Clang-LLVM.patch new file mode 100644 index 0000000000..613a002dd0 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0011-aarch64-rpi_sand-Fix-building-under-Clang-LLVM.patch @@ -0,0 +1,130 @@ +From d346c57fec8c75e2f36368a5f62f91389e9b7547 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Sat, 17 Feb 2024 13:29:36 +0000 +Subject: [PATCH 11/14] aarch64/rpi_sand: Fix building under Clang/LLVM + +The "Arm A64 Instruction Set Architecture" manual says that the MOV +(element) instruction takes the form `MOV .[], +.[]`, where `` is one of B, H, S, or D. Only certain +other instructions accept a number in front. GNU as allows you to +include it for any instruction, but this is non-standard. This is +explained at https://stackoverflow.com/questions/71907156. +--- + libavutil/aarch64/rpi_sand_neon.S | 50 +++++++++++++++---------------- + 1 file changed, 25 insertions(+), 25 deletions(-) + +diff --git a/libavutil/aarch64/rpi_sand_neon.S b/libavutil/aarch64/rpi_sand_neon.S +index 11658de0c8..3a6bc3de74 100644 +--- a/libavutil/aarch64/rpi_sand_neon.S ++++ b/libavutil/aarch64/rpi_sand_neon.S +@@ -387,13 +387,13 @@ function ff_rpi_sand30_lines_to_planar_c16, export=1 + st3 {v0.4h - v2.4h}, [x0], #24 + st3 {v16.4h - v18.4h}, [x2], #24 + beq 11b +- mov v0.2d[0], v0.2d[1] ++ mov v0.d[0], v0.d[1] + sub w9, w9, #12 +- mov v1.2d[0], v1.2d[1] +- mov v2.2d[0], v2.2d[1] +- mov v16.2d[0], v16.2d[1] +- mov v17.2d[0], v17.2d[1] +- mov v18.2d[0], v18.2d[1] ++ mov v1.d[0], v1.d[1] ++ mov v2.d[0], v2.d[1] ++ mov v16.d[0], v16.d[1] ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] + 1: + cmp w9, #6-48 + blt 1f +@@ -526,28 +526,28 @@ function ff_rpi_sand30_lines_to_planar_y16, export=1 + blt 1f + st3 {v16.4h, v17.4h, v18.4h}, [x0], #24 + beq 11b +- mov v16.2d[0], v16.2d[1] ++ mov v16.d[0], v16.d[1] + sub w5, w5, #12 +- mov v17.2d[0], v17.2d[1] +- mov v18.2d[0], v18.2d[1] ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] + 1: + cmp w5, #6-96 + blt 1f + st3 {v16.h, v17.h, v18.h}[0], [x0], #6 + st3 {v16.h, v17.h, v18.h}[1], [x0], #6 + beq 11b +- mov v16.2s[0], v16.2s[1] ++ mov v16.s[0], v16.s[1] + sub w5, w5, #6 +- mov v17.2s[0], v17.2s[1] +- mov v18.2s[0], v18.2s[1] ++ mov v17.s[0], v17.s[1] ++ mov v18.s[0], v18.s[1] + 1: + cmp w5, #3-96 + blt 1f + st3 {v16.h, v17.h, v18.h}[0], [x0], #6 + beq 11b +- mov v16.4h[0], v16.4h[1] ++ mov v16.h[0], v16.h[1] + sub w5, w5, #3 +- mov v17.4h[0], v17.4h[1] ++ mov v17.h[0], v17.h[1] + 1: + cmp w5, #2-96 + blt 1f +@@ -625,10 +625,10 @@ function ff_rpi_sand30_lines_to_planar_y8, export=1 + blt 1f + st3 {v16.8b, v17.8b, v18.8b}, [x0], #24 + beq 11b +- mov v16.2d[0], v16.2d[1] ++ mov v16.d[0], v16.d[1] + sub w5, w5, #24 +- mov v17.2d[0], v17.2d[1] +- mov v18.2d[0], v18.2d[1] ++ mov v17.d[0], v17.d[1] ++ mov v18.d[0], v18.d[1] + 1: + cmp w5, #12-96 + blt 1f +@@ -637,28 +637,28 @@ function ff_rpi_sand30_lines_to_planar_y8, export=1 + st3 {v16.b, v17.b, v18.b}[2], [x0], #3 + st3 {v16.b, v17.b, v18.b}[3], [x0], #3 + beq 11b +- mov v16.2s[0], v16.2s[1] ++ mov v16.s[0], v16.s[1] + sub w5, w5, #12 +- mov v17.2s[0], v17.2s[1] +- mov v18.2s[0], v18.2s[1] ++ mov v17.s[0], v17.s[1] ++ mov v18.s[0], v18.s[1] + 1: + cmp w5, #6-96 + blt 1f + st3 {v16.b, v17.b, v18.b}[0], [x0], #3 + st3 {v16.b, v17.b, v18.b}[1], [x0], #3 + beq 11b +- mov v16.4h[0], v16.4h[1] ++ mov v16.h[0], v16.h[1] + sub w5, w5, #6 +- mov v17.4h[0], v17.4h[1] +- mov v18.4h[0], v18.4h[1] ++ mov v17.h[0], v17.h[1] ++ mov v18.h[0], v18.h[1] + 1: + cmp w5, #3-96 + blt 1f + st3 {v16.b, v17.b, v18.b}[0], [x0], #3 + beq 11b +- mov v16.8b[0], v16.8b[1] ++ mov v16.b[0], v16.b[1] + sub w5, w5, #3 +- mov v17.8b[0], v17.8b[1] ++ mov v17.b[0], v17.b[1] + 1: + cmp w5, #2-96 + blt 1f +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0012-rtpenc-Fix-building-with-GCC-14.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0012-rtpenc-Fix-building-with-GCC-14.patch new file mode 100644 index 0000000000..f48e9bfc5c --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0012-rtpenc-Fix-building-with-GCC-14.patch @@ -0,0 +1,27 @@ +From 07ff7baa79d23620d293b03fc2445c43bdacb34a Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Sat, 17 Feb 2024 14:37:44 +0000 +Subject: [PATCH 12/14] rtpenc: Fix building with GCC 14 + +This incompatible pointer type issue became a fatal error in GCC 14. The +AVBuffer API started using size_t in 5.0 with ef6a9e5e. +--- + libavformat/rtpenc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c +index f67dc2a15a..1f1e4cb25a 100644 +--- a/libavformat/rtpenc.c ++++ b/libavformat/rtpenc.c +@@ -588,7 +588,7 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) + case AV_CODEC_ID_H264: + { + uint8_t *side_data; +- int side_data_size = 0; ++ size_t side_data_size = 0; + + side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + &side_data_size); +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0013-v4l2_req-Fix-building-against-musl-by-including-pthr.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0013-v4l2_req-Fix-building-against-musl-by-including-pthr.patch new file mode 100644 index 0000000000..cfb792af64 --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0013-v4l2_req-Fix-building-against-musl-by-including-pthr.patch @@ -0,0 +1,26 @@ +From aa44997bf59e2aca86a38cb65755861c413b2609 Mon Sep 17 00:00:00 2001 +From: James Le Cuirot +Date: Sun, 18 Feb 2024 09:18:31 +0000 +Subject: [PATCH 13/14] v4l2_req: Fix building against musl by including + pthread.h + +--- + libavcodec/v4l2_req_decode_q.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libavcodec/v4l2_req_decode_q.h b/libavcodec/v4l2_req_decode_q.h +index af7bbe1de4..27eafbc42b 100644 +--- a/libavcodec/v4l2_req_decode_q.h ++++ b/libavcodec/v4l2_req_decode_q.h +@@ -1,6 +1,8 @@ + #ifndef AVCODEC_V4L2_REQ_DECODE_Q_H + #define AVCODEC_V4L2_REQ_DECODE_Q_H + ++#include ++ + typedef struct req_decode_ent { + struct req_decode_ent * next; + struct req_decode_ent * prev; +-- +2.34.1 + diff --git a/projects/Amlogic/patches/ffmpeg/ffmpeg-0014-v4l2_buffers-Fix-init-of-drmprime-source-OUTPUT-buff.patch b/projects/Amlogic/patches/ffmpeg/ffmpeg-0014-v4l2_buffers-Fix-init-of-drmprime-source-OUTPUT-buff.patch new file mode 100644 index 0000000000..7c87b3ddcf --- /dev/null +++ b/projects/Amlogic/patches/ffmpeg/ffmpeg-0014-v4l2_buffers-Fix-init-of-drmprime-source-OUTPUT-buff.patch @@ -0,0 +1,28 @@ +From b3d4a1be1582195480c0f166744ada70f7457a5c Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Tue, 27 Feb 2024 12:57:08 +0000 +Subject: [PATCH 14/14] v4l2_buffers: Fix init of drmprime source (OUTPUT) + buffers for encode + +Previous fix for mmaped dmabuf CAPTURE buffers broke this due to failure +to note that dmabuf export wasn't wanted for OUTPUT buffers. +--- + libavcodec/v4l2_buffers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c +index e844a1a0b6..2d1db41a30 100644 +--- a/libavcodec/v4l2_buffers.c ++++ b/libavcodec/v4l2_buffers.c +@@ -1045,7 +1045,7 @@ int ff_v4l2_buffer_initialize(AVBufferRef ** pbufref, int index, V4L2Context *ct + avbuf->buf.length = avbuf->planes[0].length; + } + +- if (!want_mmap) { ++ if (V4L2_TYPE_IS_CAPTURE(ctx->type) && !want_mmap) { + // export_drm does dmabuf alloc if we aren't using v4l2 alloc + ret = v4l2_buffer_export_drm(avbuf); + if (ret) { +-- +2.34.1 +