[media] coda: pad first h.264 buffer to 512 bytes

The bitstream reader needs 512 bytes ready to read to examine the
headers in the first frame. If that frame is too small, prepend it
with a filler NAL.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Philipp Zabel 2017-03-03 09:12:49 -03:00 committed by Mauro Carvalho Chehab
parent 331e7860f3
commit 0eef89403e
3 changed files with 45 additions and 8 deletions
drivers/media/platform/coda

View File

@ -179,6 +179,25 @@ static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
} }
static int coda_bitstream_pad(struct coda_ctx *ctx, u32 size)
{
unsigned char *buf;
u32 n;
if (size < 6)
size = 6;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
coda_h264_filler_nal(size, buf);
n = kfifo_in(&ctx->bitstream_fifo, buf, size);
kfree(buf);
return (n < size) ? -ENOSPC : 0;
}
static int coda_bitstream_queue(struct coda_ctx *ctx, static int coda_bitstream_queue(struct coda_ctx *ctx,
struct vb2_v4l2_buffer *src_buf) struct vb2_v4l2_buffer *src_buf)
{ {
@ -198,10 +217,10 @@ static int coda_bitstream_queue(struct coda_ctx *ctx,
static bool coda_bitstream_try_queue(struct coda_ctx *ctx, static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
struct vb2_v4l2_buffer *src_buf) struct vb2_v4l2_buffer *src_buf)
{ {
unsigned long payload = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
int ret; int ret;
if (coda_get_bitstream_payload(ctx) + if (coda_get_bitstream_payload(ctx) + payload + 512 >=
vb2_get_plane_payload(&src_buf->vb2_buf, 0) + 512 >=
ctx->bitstream.size) ctx->bitstream.size)
return false; return false;
@ -210,6 +229,11 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
return true; return true;
} }
/* Add zero padding before the first H.264 buffer, if it is too small */
if (ctx->qsequence == 0 && payload < 512 &&
ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
coda_bitstream_pad(ctx, 512 - payload);
ret = coda_bitstream_queue(ctx, src_buf); ret = coda_bitstream_queue(ctx, src_buf);
if (ret < 0) { if (ret < 0) {
v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n");

View File

@ -15,10 +15,25 @@
#include <linux/string.h> #include <linux/string.h>
#include <coda.h> #include <coda.h>
static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 }; static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
int coda_h264_filler_nal(int size, char *p)
{
if (size < 6)
return -EINVAL;
p[0] = 0x00;
p[1] = 0x00;
p[2] = 0x00;
p[3] = 0x01;
p[4] = 0x0c;
memset(p + 5, 0xff, size - 6);
/* Add rbsp stop bit and trailing at the end */
p[size - 1] = 0x80;
return 0;
}
int coda_h264_padding(int size, char *p) int coda_h264_padding(int size, char *p)
{ {
int nal_size; int nal_size;
@ -29,10 +44,7 @@ int coda_h264_padding(int size, char *p)
return 0; return 0;
nal_size = coda_filler_size[diff]; nal_size = coda_filler_size[diff];
memcpy(p, coda_filler_nal, nal_size); coda_h264_filler_nal(nal_size, p);
/* Add rbsp stop bit and trailing at the end */
*(p + nal_size - 1) = 0x80;
return nal_size; return nal_size;
} }

View File

@ -290,6 +290,7 @@ void coda_bit_stream_end_flag(struct coda_ctx *ctx);
void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
enum vb2_buffer_state state); enum vb2_buffer_state state);
int coda_h264_filler_nal(int size, char *p);
int coda_h264_padding(int size, char *p); int coda_h264_padding(int size, char *p);
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);