media: coda: always hold back decoder jobs until we have enough bitstream payload
authorPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 5 Nov 2018 15:25:01 +0000 (10:25 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Fri, 23 Nov 2018 10:26:24 +0000 (05:26 -0500)
The bitstream prefetch unit reads data in 256 byte blocks with some kind
of queueing. For the decoder to see data up to a desired position in the
next run, the bitstream has to be filled for 2 256 byte blocks past that
position aligned up to the next 256 byte boundary.
This should make sure we never run into a buffer underrun condition if
userspace does not supply new input buffers fast enough.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hansverk@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/coda/coda-common.c
drivers/media/platform/coda/coda.h

index fbb8967dd2aa66a3ea9df6f52ba6a8b2bb135a2d..e8b380f876b6c7602ea7451c2e9a90ade70323b9 100644 (file)
@@ -1273,6 +1273,7 @@ static int coda_job_ready(void *m2m_priv)
                bool stream_end = ctx->bit_stream_param &
                                  CODA_BIT_STREAM_END_FLAG;
                int num_metas = ctx->num_metas;
+               struct coda_buffer_meta *meta;
                unsigned int count;
 
                count = hweight32(ctx->frm_dis_flg);
@@ -1293,16 +1294,18 @@ static int coda_job_ready(void *m2m_priv)
 
                if (!stream_end && (num_metas + src_bufs) < 2) {
                        v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-                                "%d: not ready: need 2 buffers available (%d, %d)\n",
+                                "%d: not ready: need 2 buffers available (queue:%d + bitstream:%d)\n",
                                 ctx->idx, num_metas, src_bufs);
                        return 0;
                }
 
-               if (!src_bufs && !stream_end &&
-                   (coda_get_bitstream_payload(ctx) < 512)) {
+               meta = list_first_entry(&ctx->buffer_meta_list,
+                                       struct coda_buffer_meta, list);
+               if (!coda_bitstream_can_fetch_past(ctx, meta->end) &&
+                   !stream_end) {
                        v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
-                                "%d: not ready: not enough bitstream data (%d).\n",
-                                ctx->idx, coda_get_bitstream_payload(ctx));
+                                "not ready: not enough bitstream data to read past %u (%u)\n",
+                                meta->end, ctx->bitstream_fifo.kfifo.in);
                        return 0;
                }
        }
index baa04b0f21fba029a0ecf64195f018a9db7a7695..e35f505053d09621e27289f496ed2e360c9c04b3 100644 (file)
@@ -296,6 +296,18 @@ static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
        return kfifo_len(&ctx->bitstream_fifo);
 }
 
+/*
+ * The bitstream prefetcher needs to read at least 2 256 byte periods past
+ * the desired bitstream position for all data to reach the decoder.
+ */
+static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx,
+                                                unsigned int pos)
+{
+       return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512;
+}
+
+bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos);
+
 void coda_bit_stream_end_flag(struct coda_ctx *ctx);
 
 void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,