diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index d675c55..f06a7ff 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -189,40 +189,6 @@ reinit_run:
     return 1;
 }
 
-static int v4l2_stop_decode(V4L2Context *ctx)
-{
-    struct v4l2_decoder_cmd cmd = {
-        .cmd = V4L2_DEC_CMD_STOP,
-    };
-    int ret;
-
-    ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd);
-    if (ret) {
-        /* DECODER_CMD is optional */
-        if (errno == ENOTTY)
-            return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
-    }
-
-    return 0;
-}
-
-static int v4l2_stop_encode(V4L2Context *ctx)
-{
-    struct v4l2_encoder_cmd cmd = {
-        .cmd = V4L2_ENC_CMD_STOP,
-    };
-    int ret;
-
-    ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_ENCODER_CMD, &cmd);
-    if (ret) {
-        /* ENCODER_CMD is optional */
-        if (errno == ENOTTY)
-            return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF);
-    }
-
-    return 0;
-}
-
 static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
 {
     struct v4l2_plane planes[VIDEO_MAX_PLANES];
@@ -236,6 +202,13 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
 
     if (V4L2_TYPE_IS_OUTPUT(ctx->type))
         pfd.events =  POLLOUT | POLLWRNORM;
+    else {
+        /* on the capture queue */
+        if (ctx_to_m2mctx(ctx)->draining) {
+            /* ignore driver requests for more input and just wait for a valid frame */
+            pfd.events = POLLIN | POLLRDNORM | POLLPRI;
+        }
+    }
 
     for (;;) {
         ret = poll(&pfd, 1, timeout);
@@ -243,50 +216,45 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
             break;
         if (errno == EINTR)
             continue;
-
-        /* timeout is being used to indicate last valid bufer when draining */
-        if (ctx_to_m2mctx(ctx)->draining)
-            ctx->done = 1;
-
         return NULL;
     }
 
-    /* 0. handle errors */
+    /* handle errors */
     if (pfd.revents & POLLERR) {
         av_log(logger(ctx), AV_LOG_WARNING, "%s POLLERR\n", ctx->name);
         return NULL;
     }
 
-    /* 1. handle resolution changes */
+    /* handle resolution changes */
     if (pfd.revents & POLLPRI) {
         ret = v4l2_handle_event(ctx);
         if (ret < 0) {
             /* if re-init failed, abort */
-            ctx->done = EINVAL;
+            ctx->done = 1;
             return NULL;
         }
         if (ret) {
             /* if re-init was successfull drop the buffer (if there was one)
-             * since we had to reconfigure capture (unmap all buffers)
-             */
+             * since we had to reconfigure capture (unmap all buffers) */
             return NULL;
         }
     }
 
-    /* 2. dequeue the buffer */
+    /* dequeue the buffer or provide more input */
     if (pfd.revents & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM)) {
 
-        if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) {
-            /* there is a capture buffer ready */
-            if (pfd.revents & (POLLIN | POLLRDNORM))
-                goto dequeue;
+        if (V4L2_TYPE_IS_OUTPUT(ctx->type))
+            goto dequeue;
 
-            /* the driver is ready to accept more input; instead of waiting for the capture
-             * buffer to complete we return NULL so input can proceed (we are single threaded)
-             */
-            if (pfd.revents & (POLLOUT | POLLWRNORM))
-                return NULL;
-        }
+        /* there is a capture buffer ready */
+        if (pfd.revents & (POLLIN | POLLRDNORM))
+            goto dequeue;
+
+        /* the driver is ready to accept more input: instead of waiting for
+         * the capture buffer to complete, return NULL so input can proceed
+         * (we are single threaded after all) */
+        if (pfd.revents & (POLLOUT | POLLWRNORM))
+            return NULL;
 
 dequeue:
         memset(&buf, 0, sizeof(buf));
@@ -301,23 +269,25 @@ dequeue:
         ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DQBUF, &buf);
         if (ret) {
             if (errno != EAGAIN) {
-                ctx->done = errno;
+                ctx->done = 1;
                 if (errno != EPIPE)
-                    av_log(logger(ctx), AV_LOG_DEBUG, "%s VIDIOC_DQBUF, errno (%s)\n",
+                    av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQBUF, errno (%s)\n",
                         ctx->name, av_err2str(AVERROR(errno)));
             }
-        } else {
-            avbuf = &ctx->buffers[buf.index];
-            avbuf->status = V4L2BUF_AVAILABLE;
-            avbuf->buf = buf;
-            if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
-                memcpy(avbuf->planes, planes, sizeof(planes));
-                avbuf->buf.m.planes = avbuf->planes;
-            }
+            return NULL;
         }
+
+        avbuf = &ctx->buffers[buf.index];
+        avbuf->status = V4L2BUF_AVAILABLE;
+        avbuf->buf = buf;
+        if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) {
+            memcpy(avbuf->planes, planes, sizeof(planes));
+            avbuf->buf.m.planes = avbuf->planes;
+        }
+        return avbuf;
     }
 
-    return avbuf;
+    return NULL;
 }
 
 static V4L2Buffer* v4l2_getfree_v4l2buf(V4L2Context *ctx)
@@ -476,50 +446,50 @@ int ff_v4l2_context_set_status(V4L2Context* ctx, int cmd)
 
 int ff_v4l2_context_enqueue_frame(V4L2Context* ctx, const AVFrame* frame)
 {
-    V4L2m2mContext *s = ctx_to_m2mctx(ctx);
     V4L2Buffer* avbuf;
     int ret;
 
-    if (!frame) {
-        ret = v4l2_stop_encode(ctx);
-        if (ret)
-            av_log(logger(ctx), AV_LOG_ERROR, "%s stop_encode\n", ctx->name);
-        s->draining= 1;
-        return 0;
-    }
-
     avbuf = v4l2_getfree_v4l2buf(ctx);
     if (!avbuf)
         return AVERROR(ENOMEM);
 
-    ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf);
-    if (ret)
-        return ret;
+    if (!frame) {
+        /* flag that we are draining */
+        ctx_to_m2mctx(ctx)->draining = 1;
+
+        /* send EOS */
+        avbuf->buf.m.planes[0].bytesused = 1;
+        avbuf->flags |= V4L2_BUF_FLAG_LAST;
+    } else {
+        ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf);
+        if (ret)
+            return ret;
+    }
 
     return ff_v4l2_buffer_enqueue(avbuf);
 }
 
 int ff_v4l2_context_enqueue_packet(V4L2Context* ctx, const AVPacket* pkt)
 {
-    V4L2m2mContext *s = ctx_to_m2mctx(ctx);
     V4L2Buffer* avbuf;
     int ret;
 
-    if (!pkt->size) {
-        ret = v4l2_stop_decode(ctx);
-        if (ret)
-            av_log(logger(ctx), AV_LOG_ERROR, "%s stop_decode\n", ctx->name);
-        s->draining = 1;
-        return 0;
-    }
-
     avbuf = v4l2_getfree_v4l2buf(ctx);
     if (!avbuf)
         return AVERROR(ENOMEM);
 
-    ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf);
-    if (ret)
-        return ret;
+    if (!pkt->size) {
+        /* flag that we are draining */
+        ctx_to_m2mctx(ctx)->draining = 1;
+
+        /* send EOS */
+        avbuf->buf.m.planes[0].bytesused = 1;
+        avbuf->flags |= V4L2_BUF_FLAG_LAST;
+    } else {
+        ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf);
+        if (ret)
+            return ret;
+    }
 
     return ff_v4l2_buffer_enqueue(avbuf);
 }
@@ -528,14 +498,12 @@ int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame)
 {
     V4L2Buffer* avbuf = NULL;
 
-    /* if we are draining, we are no longer inputing data, therefore enable a
-     * timeout so we can dequeue and flag the last valid buffer.
-     *
+    /*
      * blocks until:
      *  1. decoded frame available
      *  2. an input buffer is ready to be dequeued
      */
-    avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1);
+    avbuf = v4l2_dequeue_v4l2buf(ctx, -1);
     if (!avbuf) {
         if (ctx->done)
             return AVERROR_EOF;
@@ -550,14 +518,12 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt)
 {
     V4L2Buffer* avbuf = NULL;
 
-    /* if we are draining, we are no longer inputing data, therefore enable a
-     * timeout so we can dequeue and flag the last valid buffer.
-     *
+    /*
      * blocks until:
      *  1. encoded packet available
      *  2. an input buffer ready to be dequeued
      */
-    avbuf = v4l2_dequeue_v4l2buf(ctx, ctx_to_m2mctx(ctx)->draining ? 200 : -1);
+    avbuf = v4l2_dequeue_v4l2buf(ctx, -1);
     if (!avbuf) {
         if (ctx->done)
             return AVERROR_EOF;
