@@ -30,6 +30,7 @@
#include <poll.h>
#include "libavcodec/avcodec.h"
#include "libavcodec/internal.h"
+#include "libavutil/avassert.h"
#include "libavutil/hwcontext.h"
#include "v4l2_context.h"
#include "v4l2_buffers.h"
@@ -446,6 +447,31 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
av_frame_unref(frame);
+ if (!s->device_ref) {
+ AVHWDeviceContext *dev;
+ AVDRMDeviceContext *drm_dev;
+ s->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DRM);
+ av_assert0(s->device_ref);
+ dev = (AVHWDeviceContext*)s->device_ref->data;
+ drm_dev = dev->hwctx;
+ // V4L2 is not associated with any DRM device.
+ drm_dev->fd = -1;
+ ret = av_hwdevice_ctx_init(s->device_ref);
+ av_assert0(ret == 0);
+ }
+ if (!s->frames_ref) {
+ AVHWFramesContext *frames;
+ s->frames_ref = av_hwframe_ctx_alloc(s->device_ref);
+ av_assert0(s->frames_ref);
+ frames = (AVHWFramesContext*)s->frames_ref->data;
+ frames->width = s->output.width;
+ frames->height = s->output.height;
+ frames->format = AV_PIX_FMT_DRM_PRIME;
+ frames->sw_format = avbuf->context->av_pix_fmt;
+ ret = av_hwframe_ctx_init(s->frames_ref);
+ av_assert0(ret == 0);
+ }
+
if (buf_to_m2mctx(avbuf)->output_drm) {
/* 1. get references to the actual data */
ret = v4l2_buf_to_bufref_drm(avbuf, &frame->buf[0]);
@@ -454,6 +480,9 @@ int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf)
frame->data[0] = (uint8_t *) v4l2_get_drm_frame(avbuf);
frame->format = AV_PIX_FMT_DRM_PRIME;
+
+ frame->hw_frames_ctx = av_buffer_ref(s->frames_ref);
+ av_assert0(frame->hw_frames_ctx);
} else {
/* 1. get references to the actual data */
for (i = 0; i < avbuf->num_planes; i++) {
@@ -62,6 +62,9 @@ typedef struct V4L2m2mContext {
/* generate DRM frames */
int output_drm;
+
+ AVBufferRef *device_ref;
+ AVBufferRef *frames_ref;
} V4L2m2mContext;
typedef struct V4L2m2mPriv