diff --git a/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch index 2497998e5d..0810fee4dc 100644 --- a/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch +++ b/packages/multimedia/ffmpeg/patches/rpi/ffmpeg-001-rpi.patch @@ -16116,7 +16116,7 @@ index 0000000000..13698d3f33 + +#endif diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c -index 0772608a30..91a7536ee5 100644 +index 0772608a30..c30fb2a83f 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -372,14 +372,20 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) @@ -16186,14 +16186,14 @@ index 0772608a30..91a7536ee5 100644 #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL HWACCEL_VIDEOTOOLBOX(hevc), +#endif -+#if CONFIG_HEVC_V4L2REQUEST_HWACCEL -+ HWACCEL_V4L2REQUEST(hevc), -+#endif +#if CONFIG_HEVC_RPI4_8_HWACCEL + HWACCEL_RPI4_8(hevc), +#endif +#if CONFIG_HEVC_RPI4_10_HWACCEL + HWACCEL_RPI4_10(hevc), ++#endif ++#if CONFIG_HEVC_V4L2REQUEST_HWACCEL ++ HWACCEL_V4L2REQUEST(hevc), #endif NULL }, @@ -47232,7 +47232,7 @@ index 8dbc7fc104..46ca85ce65 100644 * Extracts the data from an AVFrame to a V4L2Buffer * diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c -index 29b144ed73..31b406769b 100644 +index 29b144ed73..97956eeb2b 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -173,7 +173,8 @@ static int v4l2_handle_event(V4L2Context *ctx) @@ -47347,15 +47347,18 @@ index 29b144ed73..31b406769b 100644 #endif } -@@ -455,22 +498,54 @@ static int v4l2_release_buffers(V4L2Context* ctx) - struct v4l2_requestbuffers req = { - .memory = V4L2_MEMORY_MMAP, - .type = ctx->type, +@@ -452,25 +495,62 @@ static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx) + + static int v4l2_release_buffers(V4L2Context* ctx) + { +- struct v4l2_requestbuffers req = { +- .memory = V4L2_MEMORY_MMAP, +- .type = ctx->type, - .count = 0, /* 0 -> unmaps buffers from the driver */ -+ .count = 0, /* 0 -> unmap all buffers from the driver */ - }; -- int i, j; -+ int ret, i, j; +- }; + int i, j; ++ int ret = 0; ++ const int fd = ctx_to_m2mctx(ctx)->fd; for (i = 0; i < ctx->num_buffers; i++) { V4L2Buffer *buffer = &ctx->buffers[i]; @@ -47389,24 +47392,32 @@ index 29b144ed73..31b406769b 100644 } - return ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); -+ ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_REQBUFS, &req); -+ if (ret < 0) { -+ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n", -+ ctx->name, av_err2str(AVERROR(errno))); ++ if (fd != -1) { ++ struct v4l2_requestbuffers req = { ++ .memory = V4L2_MEMORY_MMAP, ++ .type = ctx->type, ++ .count = 0, /* 0 -> unmap all buffers from the driver */ ++ }; + -+ if (ctx_to_m2mctx(ctx)->output_drm) -+ av_log(logger(ctx), AV_LOG_ERROR, -+ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n" -+ "for all buffers: \n" -+ " 1. drmModeRmFB(..)\n" -+ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n"); ++ ret = ioctl(fd, VIDIOC_REQBUFS, &req); ++ if (ret < 0) { ++ av_log(logger(ctx), AV_LOG_ERROR, "release all %s buffers (%s)\n", ++ ctx->name, av_err2str(AVERROR(errno))); ++ ++ if (ctx_to_m2mctx(ctx)->output_drm) ++ av_log(logger(ctx), AV_LOG_ERROR, ++ "Make sure the DRM client releases all FB/GEM objects before closing the codec (ie):\n" ++ "for all buffers: \n" ++ " 1. drmModeRmFB(..)\n" ++ " 2. drmIoctl(.., DRM_IOCTL_GEM_CLOSE,... )\n"); ++ } + } + + return ret; } static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfmt) -@@ -499,6 +574,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm +@@ -499,6 +579,8 @@ static inline int v4l2_try_raw_format(V4L2Context* ctx, enum AVPixelFormat pixfm static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) { @@ -47415,7 +47426,7 @@ index 29b144ed73..31b406769b 100644 enum AVPixelFormat pixfmt = ctx->av_pix_fmt; struct v4l2_fmtdesc fdesc; int ret; -@@ -517,6 +594,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) +@@ -517,6 +599,13 @@ static int v4l2_get_raw_format(V4L2Context* ctx, enum AVPixelFormat *p) if (ret) return AVERROR(EINVAL); @@ -47429,7 +47440,7 @@ index 29b144ed73..31b406769b 100644 pixfmt = ff_v4l2_format_v4l2_to_avfmt(fdesc.pixelformat, AV_CODEC_ID_RAWVIDEO); ret = v4l2_try_raw_format(ctx, pixfmt); if (ret){ -@@ -575,10 +659,16 @@ int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) +@@ -575,10 +664,16 @@ int ff_v4l2_context_set_status(V4L2Context* ctx, uint32_t cmd) int ret; ret = ioctl(ctx_to_m2mctx(ctx)->fd, cmd, &type); @@ -47448,7 +47459,7 @@ index 29b144ed73..31b406769b 100644 return 0; } -@@ -608,7 +698,8 @@ int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) +@@ -608,7 +703,8 @@ int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame) return ff_v4l2_buffer_enqueue(avbuf); } @@ -47458,7 +47469,7 @@ index 29b144ed73..31b406769b 100644 { V4L2m2mContext *s = ctx_to_m2mctx(ctx); V4L2Buffer* avbuf; -@@ -616,8 +707,9 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) +@@ -616,8 +712,9 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) if (!pkt->size) { ret = v4l2_stop_decode(ctx); @@ -47469,7 +47480,7 @@ index 29b144ed73..31b406769b 100644 s->draining = 1; return 0; } -@@ -626,14 +718,14 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) +@@ -626,14 +723,14 @@ int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt) if (!avbuf) return AVERROR(EAGAIN); @@ -47486,7 +47497,7 @@ index 29b144ed73..31b406769b 100644 { V4L2Buffer *avbuf; -@@ -650,7 +742,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) +@@ -650,7 +747,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) return AVERROR(EAGAIN); } @@ -47496,20 +47507,19 @@ index 29b144ed73..31b406769b 100644 int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h -index 22a9532444..3484a25a9c 100644 +index 22a9532444..5588e4a460 100644 --- a/libavcodec/v4l2_context.h +++ b/libavcodec/v4l2_context.h -@@ -92,6 +92,9 @@ typedef struct V4L2Context { +@@ -92,6 +92,8 @@ typedef struct V4L2Context { */ int done; + AVBufferRef *frames_ref; + int q_count; -+ } V4L2Context; /** -@@ -156,9 +159,12 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt); +@@ -156,9 +158,12 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt); * @param[in] ctx The V4L2Context to dequeue from. * @param[inout] f The AVFrame to dequeue to. * @param[in] timeout The timeout for dequeue (-1 to block, 0 to return immediately, or milliseconds) @@ -47523,7 +47533,7 @@ index 22a9532444..3484a25a9c 100644 /** * Enqueues a buffer to a V4L2Context from an AVPacket -@@ -170,7 +176,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); +@@ -170,7 +175,7 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); * @param[in] pkt A pointer to an AVPacket. * @return 0 in case of success, a negative error otherwise. */ @@ -47533,10 +47543,22 @@ index 22a9532444..3484a25a9c 100644 /** * Enqueues a buffer to a V4L2Context from an AVFrame diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c -index e48b3a8ccf..cac2b3e2f2 100644 +index e48b3a8ccf..b994e39ad6 100644 --- a/libavcodec/v4l2_m2m.c +++ b/libavcodec/v4l2_m2m.c -@@ -338,18 +338,30 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) +@@ -328,7 +328,10 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) + ff_v4l2_context_release(&s->capture); + sem_destroy(&s->refsync); + +- close(s->fd); ++ if (s->fd != -1) ++ close(s->fd); ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Context destroyed\n"); + + av_free(s); + } +@@ -338,17 +341,34 @@ int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) V4L2m2mContext *s = priv->context; int ret; @@ -47549,6 +47571,8 @@ index e48b3a8ccf..cac2b3e2f2 100644 - ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); - if (ret) - av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ av_log(s->avctx, AV_LOG_DEBUG, "V4L2 Codec end\n"); ++ + if (av_codec_is_decoder(s->avctx->codec)) + av_packet_unref(&s->buf_pkt); + @@ -47564,15 +47588,17 @@ index e48b3a8ccf..cac2b3e2f2 100644 ff_v4l2_context_release(&s->output); ++ close(s->fd); ++ s->fd = -1; ++ s->self_ref = NULL; + // This is only called on avctx close so after this point we don't have that + // Crash sooner if we find we are using it (can still log with avctx = NULL) + s->avctx = NULL; - av_buffer_unref(&priv->context_ref); + priv->context = NULL; + av_buffer_unref(&priv->context_ref); return 0; - } diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h index 456281f48c..b08a5b38ac 100644 --- a/libavcodec/v4l2_m2m.h @@ -47638,7 +47664,7 @@ index 456281f48c..b08a5b38ac 100644 /** diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c -index 3e17e0fcac..678d390103 100644 +index 3e17e0fcac..e774532e36 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -23,6 +23,10 @@ @@ -47729,18 +47755,13 @@ index 3e17e0fcac..678d390103 100644 /* 3. set the crop parameters */ selection.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -@@ -133,54 +168,286 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) +@@ -133,54 +168,293 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) return 0; } -static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) +static inline int64_t track_to_pts(AVCodecContext *avctx, unsigned int n) - { -- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; -- V4L2Context *const capture = &s->capture; -- V4L2Context *const output = &s->output; -- AVPacket avpkt = {0}; -- int ret; ++{ + return (int64_t)n; +} + @@ -47835,13 +47856,7 @@ index 3e17e0fcac..678d390103 100644 +#define NQ_SRC_EMPTY 2 +#define NQ_DRAINING 3 +#define NQ_DEAD 4 - -- if (s->buf_pkt.size) { -- avpkt = s->buf_pkt; -- memset(&s->buf_pkt, 0, sizeof(AVPacket)); -- } else { -- ret = ff_decode_get_packet(avctx, &avpkt); -- if (ret < 0 && ret != AVERROR_EOF) ++ +#define TRY_DQ(nq_status) ((nq_status) >= NQ_OK && (nq_status) <= NQ_DRAINING) + +// AVERROR_EOF Flushing an already flushed stream @@ -47853,10 +47868,22 @@ index 3e17e0fcac..678d390103 100644 +// NQ_DEAD Not running (do not retry, do not attempt capture dQ) + +static int try_enqueue_src(AVCodecContext * const avctx, V4L2m2mContext * const s) -+{ -+ int ret = 0; -+ int ret2 = 0; -+ + { +- V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; +- V4L2Context *const capture = &s->capture; +- V4L2Context *const output = &s->output; +- AVPacket avpkt = {0}; + int ret; + +- if (s->buf_pkt.size) { +- avpkt = s->buf_pkt; +- memset(&s->buf_pkt, 0, sizeof(AVPacket)); +- } else { +- ret = ff_decode_get_packet(avctx, &avpkt); +- if (ret < 0 && ret != AVERROR_EOF) ++ // If we don't already have a coded packet - get a new one ++ // We will already have a coded pkt if the output Q was full last time we ++ // tried to Q it + if (!s->buf_pkt.size) { + ret = ff_decode_get_packet(avctx, &s->buf_pkt); + @@ -47931,14 +47958,20 @@ index 3e17e0fcac..678d390103 100644 + return ret; + } + } -+ + +- /* cant recover */ +- if (ret == AVERROR(ENOMEM)) +- return ret; + // Start if we haven't -+ ret2 = v4l2_try_start(avctx); -+ if (ret2) { -+ av_log(avctx, AV_LOG_DEBUG, "Start failure: err=%d\n", ret2); -+ ret = (ret2 == AVERROR(ENOMEM)) ? ret2 : NQ_DEAD; ++ { ++ const int ret2 = v4l2_try_start(avctx); ++ if (ret2) { ++ av_log(avctx, AV_LOG_DEBUG, "Start failure: err=%d\n", ret2); ++ ret = (ret2 == AVERROR(ENOMEM)) ? ret2 : NQ_DEAD; ++ } + } -+ + +- return 0; + return ret; +} + @@ -47962,17 +47995,15 @@ index 3e17e0fcac..678d390103 100644 + av_log(avctx, AV_LOG_WARNING, "Poll says src Q has space but enqueue fail"); + src_rv = NQ_SRC_EMPTY; // If we can't enqueue pretend that there is nothing to enqueue + } - -- /* cant recover */ -- if (ret == AVERROR(ENOMEM)) -- return ret; ++ + // Try to get a new frame if + // (a) we haven't already got one AND + // (b) enqueue returned a status indicating that decode should be attempted + if (dst_rv != 0 && TRY_DQ(src_rv)) { + do { + // Dequeue frame will unref any previous contents of frame -+ // so we don't need an explicit unref when discarding ++ // if it returns success so we don't need an explicit unref ++ // when discarding + // This returns AVERROR(EAGAIN) if there isn't a frame ready yet + // but there is room in the input Q + dst_rv = ff_v4l2_context_dequeue_frame(&s->capture, frame, -1, 1); @@ -47987,13 +48018,14 @@ index 3e17e0fcac..678d390103 100644 + // Go again if we got a frame that we need to discard + } while (dst_rv == 0 && xlat_pts_out(avctx, s, frame)); + } - -- return 0; ++ + // Continue trying to enqueue packets if either + // (a) we succeeded last time OR + // (b) enqueue failed due to input Q full AND there is now room + } while (src_rv == NQ_OK || (src_rv == NQ_Q_FULL && dst_rv == AVERROR(EAGAIN)) ); + ++ // Ensure that the frame contains nothing if we aren't returning a frame ++ // (might happen when discarding) + if (dst_rv) + av_frame_unref(frame); + @@ -48047,7 +48079,7 @@ index 3e17e0fcac..678d390103 100644 static av_cold int v4l2_decode_init(AVCodecContext *avctx) { V4L2Context *capture, *output; -@@ -188,6 +455,9 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) +@@ -188,6 +462,9 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) V4L2m2mPriv *priv = avctx->priv_data; int ret; @@ -48057,7 +48089,7 @@ index 3e17e0fcac..678d390103 100644 ret = ff_v4l2_m2m_create_context(priv, &s); if (ret < 0) return ret; -@@ -208,13 +478,32 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) +@@ -208,13 +485,32 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; capture->av_pix_fmt = avctx->pix_fmt; @@ -48093,7 +48125,7 @@ index 3e17e0fcac..678d390103 100644 return ret; } -@@ -223,10 +512,59 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) +@@ -223,10 +519,59 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) static av_cold int v4l2_decode_close(AVCodecContext *avctx) { @@ -48156,7 +48188,7 @@ index 3e17e0fcac..678d390103 100644 } #define OFFSET(x) offsetof(V4L2m2mPriv, x) -@@ -235,10 +573,16 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) +@@ -235,10 +580,16 @@ static av_cold int v4l2_decode_close(AVCodecContext *avctx) static const AVOption options[] = { V4L_M2M_DEFAULT_OPTS, { "num_capture_buffers", "Number of buffers in the capture context", @@ -48174,7 +48206,7 @@ index 3e17e0fcac..678d390103 100644 #define M2MDEC_CLASS(NAME) \ static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ .class_name = #NAME "_v4l2m2m_decoder", \ -@@ -259,9 +603,14 @@ static const AVOption options[] = { +@@ -259,9 +610,14 @@ static const AVOption options[] = { .init = v4l2_decode_init, \ .receive_frame = v4l2_receive_frame, \ .close = v4l2_decode_close, \