tpf_max = {.numerator = 1, .denominator = FPS_MIN},
tpf_default = {.numerator = 1000, .denominator = 30000};
+/* Container for MMAL and VB2 buffers*/
+struct vb2_mmal_buffer {
+ struct vb2_v4l2_buffer vb;
+ struct mmal_buffer mmal;
+};
+
/* video formats */
static struct mmal_fmt formats[] = {
{
return -EINVAL;
}
+ /* Handle CREATE_BUFS situation - *nplanes != 0 */
+ if (*nplanes) {
+ if (*nplanes != 1 ||
+ sizes[0] < dev->capture.port->current_buffer.size) {
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n",
+ __func__, dev, sizes[0],
+ dev->capture.port->current_buffer.size,
+ *nplanes);
+ return -EINVAL;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Handle REQBUFS situation */
size = dev->capture.port->current_buffer.size;
if (size == 0) {
v4l2_err(&dev->v4l2_dev,
{
struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
- struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+ struct vb2_mmal_buffer *buf =
+ container_of(vb2, struct vb2_mmal_buffer, vb);
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
__func__, dev, vb);
- buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+ buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+ buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
- return mmal_vchi_buffer_init(dev->instance, buf);
+ return mmal_vchi_buffer_init(dev->instance, &buf->mmal);
}
static int buffer_prepare(struct vb2_buffer *vb)
{
struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
- struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+ struct vb2_mmal_buffer *buf =
+ container_of(vb2, struct vb2_mmal_buffer, vb);
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
__func__, dev, vb);
- mmal_vchi_buffer_cleanup(buf);
+
+ mmal_vchi_buffer_cleanup(&buf->mmal);
}
static inline bool is_capturing(struct bm2835_mmal_dev *dev)
static void buffer_cb(struct vchiq_mmal_instance *instance,
struct vchiq_mmal_port *port,
int status,
- struct mmal_buffer *buf,
- unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
+ struct mmal_buffer *mmal_buf)
{
struct bm2835_mmal_dev *dev = port->cb_ctx;
+ struct vb2_mmal_buffer *buf =
+ container_of(mmal_buf, struct vb2_mmal_buffer, mmal);
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
- __func__, status, buf, length, mmal_flags, pts);
+ __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags,
+ mmal_buf->pts);
if (status != 0) {
/* error in transfer */
return;
}
- if (length == 0) {
+ if (mmal_buf->length == 0) {
/* stream ended */
if (dev->capture.frame_count) {
/* empty buffer whilst capturing - expected to be an
&dev->capture.frame_count,
sizeof(dev->capture.frame_count));
}
- if (vchiq_mmal_submit_buffer(instance, port, buf))
+ if (vchiq_mmal_submit_buffer(instance, port,
+ &buf->mmal))
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Failed to return EOS buffer");
} else {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Buffer time set as current time - %lld",
buf->vb.vb2_buf.timestamp);
- } else if (pts != 0) {
+ } else if (mmal_buf->pts != 0) {
ktime_t timestamp;
- s64 runtime_us = pts -
+ s64 runtime_us = mmal_buf->pts -
dev->capture.vc_start_timestamp;
timestamp = ktime_add_us(dev->capture.kernel_start_ts,
runtime_us);
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Convert start time %llu and %llu with offset %llu to %llu\n",
ktime_to_ns(dev->capture.kernel_start_ts),
- dev->capture.vc_start_timestamp, pts,
+ dev->capture.vc_start_timestamp, mmal_buf->pts,
ktime_to_ns(timestamp));
if (timestamp < dev->capture.last_timestamp) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
}
dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp;
buf->vb.sequence = dev->capture.sequence++;
+ buf->vb.field = V4L2_FIELD_NONE;
- vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length);
- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length);
+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Buffer has ts %llu", dev->capture.last_timestamp);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
- if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
+ if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
is_capturing(dev)) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"Grab another frame as buffer has EOS");
{
struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
- struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+ struct vb2_mmal_buffer *buf =
+ container_of(vb2, struct vb2_mmal_buffer, vb);
int ret;
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"%s: dev:%p buf:%p, idx %u\n",
__func__, dev, buf, vb2->vb2_buf.index);
- ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
+ ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port,
+ &buf->mmal);
if (ret < 0)
v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
__func__);
dev->capture.frame_count = 0;
/* ensure a format has actually been set */
- if (!dev->capture.port) {
+ if (!port) {
v4l2_err(&dev->v4l2_dev,
"no capture port - stream not started?\n");
return;
/* disable the connection from camera to encoder */
ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
- if (!ret && dev->capture.camera_port != dev->capture.port) {
+ if (!ret && dev->capture.camera_port != port) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
"disabling port\n");
- ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
- } else if (dev->capture.camera_port != dev->capture.port) {
+ ret = vchiq_mmal_port_disable(dev->instance, port);
+ } else if (dev->capture.camera_port != port) {
v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
ret);
}
1, 0);
f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
if (!mfmt->remove_padding) {
- int align_mask = ((32 * mfmt->depth) >> 3) - 1;
- /* GPU isn't removing padding, so stride is aligned to 32 */
- f->fmt.pix.bytesperline =
- (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
+ if (mfmt->depth == 24) {
+ /*
+ * 24bpp is a pain as we can't use simple masking.
+ * Min stride is width aligned to 16, times 24bpp.
+ */
+ f->fmt.pix.bytesperline =
+ ((f->fmt.pix.width + 15) & ~15) * 3;
+ } else {
+ /*
+ * GPU isn't removing padding, so stride is aligned to
+ * 32
+ */
+ int align_mask = ((32 * mfmt->depth) >> 3) - 1;
+
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.bytesperline + align_mask) &
+ ~align_mask;
+ }
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
- "Not removing padding, so bytes/line = %d, (align_mask %d)\n",
- f->fmt.pix.bytesperline, align_mask);
+ "Not removing padding, so bytes/line = %d\n",
+ f->fmt.pix.bytesperline);
}
/* Image buffer has to be padded to allow for alignment, even though
/* Make a further decision on port based on resolution */
if (f->fmt.pix.width <= max_video_width &&
f->fmt.pix.height <= max_video_height)
- camera_port = port =
+ camera_port =
&dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO];
else
- camera_port = port =
+ camera_port =
&dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE];
+ port = camera_port;
break;
case COMP_IMAGE_ENCODE:
encode_component = dev->component[COMP_IMAGE_ENCODE];
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct mmal_buffer);
+ q->buf_struct_size = sizeof(struct vb2_mmal_buffer);
q->ops = &bm2835_mmal_video_qops;
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;