Skip to content

Commit

Permalink
ffmpeg: Update to avoid double frame buffer allocation when looping s…
Browse files Browse the repository at this point in the history
…tateful v4l2
  • Loading branch information
popcornmix committed Jan 29, 2021
1 parent c5caefd commit ffc173b
Showing 1 changed file with 65 additions and 39 deletions.
104 changes: 65 additions & 39 deletions tools/depends/target/ffmpeg/0001-rpi-Add-hevc-acceleration.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
},
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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);
}

Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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);
}

Expand All @@ -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)
Expand All @@ -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.
*/
Expand All @@ -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;

Expand All @@ -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);
+
Expand All @@ -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
Expand Down

0 comments on commit ffc173b

Please sign in to comment.