diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 5bbdec55b7d7..e00277e175f3 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -43,8 +43,10 @@ module_param(debug, bool, 0644);
 #define TRANS_QUEUED		(1 << 0)
 /* Instance is currently running in hardware */
 #define TRANS_RUNNING		(1 << 1)
+/* Instance is writing the result */
+#define TRANS_WRITING		(1 << 2)
 /* Instance is currently aborting */
-#define TRANS_ABORT		(1 << 2)
+#define TRANS_ABORT		(1 << 3)
 
 
 /* Offset base for buffers on the destination queue - used to distinguish
@@ -253,9 +255,10 @@ EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
 static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
 {
 	unsigned long flags;
+	bool is_writing;
 
 	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
-	if (NULL != m2m_dev->curr_ctx) {
+	if (m2m_dev->curr_ctx) {
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 		dprintk("Another instance is running, won't run now\n");
 		return;
@@ -274,6 +277,15 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
 
 	dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx);
 	m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv);
+
+	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
+	is_writing = m2m_dev->curr_ctx &&
+		v4l2_m2m_num_dst_bufs_ready(m2m_dev->curr_ctx) &&
+		(m2m_dev->curr_ctx->job_flags & TRANS_WRITING);
+	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
+
+	if (is_writing)
+		m2m_dev->m2m_ops->job_write(m2m_dev->curr_ctx->priv);
 }
 
 /*
@@ -326,8 +338,8 @@ static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
 	spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
 	spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out);
 
-	if (m2m_dev->m2m_ops->job_ready
-		&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
+	if (m2m_dev->m2m_ops->job_ready &&
+	    !m2m_dev->m2m_ops->job_ready(m2m_ctx->priv)) {
 		dprintk("Driver not ready\n");
 		goto job_unlock;
 	}
@@ -384,7 +396,8 @@ static void v4l2_m2m_device_run_work(struct work_struct *work)
  * @m2m_ctx: m2m context with jobs to be canceled
  *
  * In case of streamoff or release called on any context,
- * 1] If the context is currently running, then abort job will be called
+ * 1] If the context is currently running or writing, then abort job will be
+ *    called
  * 2] If the context is queued, then the context will be removed from
  *    the job_queue
  */
@@ -397,16 +410,19 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx)
 	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
 
 	m2m_ctx->job_flags |= TRANS_ABORT;
-	if (m2m_ctx->job_flags & TRANS_RUNNING) {
+	if (m2m_ctx->job_flags & (TRANS_RUNNING | TRANS_WRITING)) {
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 		if (m2m_dev->m2m_ops->job_abort)
 			m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
+		if (m2m_ctx->job_flags & TRANS_WRITING)
+			v4l2_m2m_job_finish(m2m_dev, m2m_ctx);
 		dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx);
-		wait_event(m2m_ctx->finished,
-				!(m2m_ctx->job_flags & TRANS_RUNNING));
+		wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags &
+					(TRANS_RUNNING | TRANS_WRITING)));
 	} else if (m2m_ctx->job_flags & TRANS_QUEUED) {
 		list_del(&m2m_ctx->queue);
-		m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
+		m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING |
+					TRANS_WRITING);
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 		dprintk("m2m_ctx: %p had been on queue and was removed\n",
 			m2m_ctx);
@@ -416,6 +432,26 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx)
 	}
 }
 
+void v4l2_m2m_job_writing(struct v4l2_m2m_dev *m2m_dev,
+			  struct v4l2_m2m_ctx *m2m_ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
+	if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) {
+		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
+		dprintk("Called by an instance not currently running\n");
+		return;
+	}
+
+	m2m_dev->curr_ctx->job_flags &= ~TRANS_RUNNING;
+	m2m_dev->curr_ctx->job_flags |= TRANS_WRITING;
+
+	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
+}
+EXPORT_SYMBOL(v4l2_m2m_job_writing);
+
+
 void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
 			 struct v4l2_m2m_ctx *m2m_ctx)
 {
@@ -429,7 +465,8 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
 	}
 
 	list_del(&m2m_dev->curr_ctx->queue);
-	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
+	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING |
+					  TRANS_WRITING);
 	wake_up(&m2m_dev->curr_ctx->finished);
 	m2m_dev->curr_ctx = NULL;
 
@@ -504,6 +541,10 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		return -EPERM;
 	}
 	ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
+	if (!ret && !V4L2_TYPE_IS_OUTPUT(vq->type) &&
+	    (m2m_ctx->job_flags & TRANS_WRITING))
+		m2m_ctx->m2m_dev->m2m_ops->job_write(m2m_ctx->priv);
+
 	if (!ret && !(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
 		v4l2_m2m_try_schedule(m2m_ctx);
 
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 5467264771ec..380f8aea9191 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -25,13 +25,18 @@
  *		callback.
  *		The job does NOT have to end before this callback returns
  *		(and it will be the usual case). When the job finishes,
- *		v4l2_m2m_job_finish() has to be called.
+ *		v4l2_m2m_job_writing() or v4l2_m2m_job_finish() has to be called.
  * @job_ready:	optional. Should return 0 if the driver does not have a job
  *		fully prepared to run yet (i.e. it will not be able to finish a
  *		transaction without sleeping). If not provided, it will be
  *		assumed that one source and one destination buffer are all
  *		that is required for the driver to perform one full transaction.
  *		This method may not sleep.
+ * @job_write:	optional. After v4l2_m2m_job_writing() was called, this callback
+ *		is called whenever a new capture buffer was queued so the result
+ *		of the job can be written to the newly queued buffer(s). Once the
+ *		full result has been written the job can be finished by calling
+ *		v4l2_m2m_job_finish().
  * @job_abort:	optional. Informs the driver that it has to abort the currently
  *		running transaction as soon as possible (i.e. as soon as it can
  *		stop the device safely; e.g. in the next interrupt handler),
@@ -44,6 +49,7 @@
 struct v4l2_m2m_ops {
 	void (*device_run)(void *priv);
 	int (*job_ready)(void *priv);
+	void (*job_write)(void *priv);
 	void (*job_abort)(void *priv);
 };
 
@@ -159,6 +165,25 @@ struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
  */
 void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx);
 
+/**
+ * v4l2_m2m_job_writing() - inform the framework that the result of the job
+ * is ready and is now being written to capture buffers
+ *
+ * @m2m_dev: opaque pointer to the internal data to handle M2M context
+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx
+ *
+ * Called by a driver if the resulting data of the job is being written to
+ * capture buffers. This means that whenever a new capture buffer is queued
+ * up the &v4l2_m2m_ops->job_write callback is called. Once all the data has
+ * been written v4l2_m2m_job_finish() is called.
+ *
+ * This is typically only needed by stateful encoders where it is not known
+ * until the compressed data arrives how many capture buffers are needed to
+ * store the result and it has to wait for new capture buffers to be queued.
+ */
+void v4l2_m2m_job_writing(struct v4l2_m2m_dev *m2m_dev,
+			  struct v4l2_m2m_ctx *m2m_ctx);
+
 /**
  * v4l2_m2m_job_finish() - inform the framework that a job has been finished
  * and have it clean up
