Em Sun, 5 Feb 2017 22:15:21 +0000
Dave Stevenson <linux-media@xxxxxxxxxxxxxxxxxxxxxxxxxxx> escreveu:
If the goal was to protect some IP related to the sensors, I guess
this is not going to protect anything, as there are recent driver
submissions on linux-media for the ov5647 driver:
https://patchwork.kernel.org/patch/9472441/
There are also open source drivers for the Sony imx219 camera
floating around for android and chromeOS:
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/factory-ryu-6486.14.B-chromeos-3.14/drivers/media/i2c/soc_camera/imx219.c
https://android.googlesource.com/kernel/bcm/+/android-bcm-tetra-3.10-lollipop-wear-release/drivers/media/video/imx219.c
Plus, there's a datasheet (with another driver) available at:
https://github.com/rellimmot/Sony-IMX219-Raspberry-Pi-V2-CMOS
So, you're not really protecting IP here.
If the goal is to protect some proprietary algorithm meant to enhance
the camera captured streams, doing things like (auto-focus, auto-white
adjustments, scaling, etc), and/or implementing codec encoders, you should,
instead, restructure such codecs as mem2mem V4L2 drivers. There are a bunch
of such codecs already for other SoC where such functions are implemented
on GPU.
If you add DMABUF capabilities and media controller to the capture
driver and to the mem2mem drivers, userspace can use the V4L2 APIs
to use those modules using the arrangements they need, without
performance impacts.
So, by obfuscating the code, you're not protecting anything. Just making
harder for RPi customers to use, as you're providing a driver that is
limited.
Greg was kick on merging it on staging ;) Anyway, the real review
will happen when the driver becomes ready to be promoted out of
staging. When you address the existing issues and get it ready to
merge, please send the patch with such changes to linux-media ML.
I'll do a full review on it by then.
Is that even likely given the dependence on VCHI? I wasn't expecting
VCHI to leave staging, which would force this to remain too.
I didn't analyze the VCHI driver. As I said before, if you rewrite
the driver in a way that the Kernel can actually see the sensors
via an I2C interface, you probably can get rid of the VCHI interface
for the capture part.
You could take a look on the other mem2mem drivers and see if are
there some way to provide an interface for the GPU encoders in a
similar way to what those drivers do.
That seems a terrible hack! let the user specify the resolution via
modprobe parameter... That should depend on the hardware capabilities
instead.
This is sitting on top of an OpenMaxIL style camera component (though
accessed via MMAL - long story, but basically MMAL removed a bundle of
the ugly/annoying parts of IL).
It has the extension above V1.1.2 that you have a preview port, video
capture port, and stills capture port. Stills captures have additional
processing stages to improve image quality, whilst video has to maintain
framerate.
I see.
If you're asked for YUV or RGB frame, how do you choose between video or
stills? That's what is being set with these parameters, not the sensor
resolution. Having independent stills and video processing options
doesn't appear to be something that is supported in V4L2, but I'm open
to suggestions.
At the capture stage:
Assuming that the user wants to use different resolutions for video and
stills (for example, you're seeing a real time video, then you "click"
to capture a still image), you can create two buffer groups, one for
low-res video and another one for high-res image. When the button is
clicked, it will stop the low-res stream, set the parameters for the
high-res image and capture it.
For post-processing stage:
Switch the media pipeline via the media controller adding the post
processing codecs that will enhance the image.
We're discussing for a while (and there are patches floating around)
ways to improve it via the request API (with would allow different
configs to be ready to be use allowing to switch between those
settings in an atomic way, reducing the time to switch from different
configs).
There were thoughts that they could be exposed as different /dev/videoN
devices, but that then poses a quandry to the client app as to which
node to open, so complicates the client significantly. On the plus side
it would then allow for things like zero shutter lag captures, and
stills during video, where you want multiple streams (apparently)
simultaneously, but is that worth the complexity? The general view was no.
IMHO, that's the best option if you want to give flexibility to
user apps. Those that don't want/need it, could just setup the
pipeline via media-ctl and use any V4L application to get images from
a single /dev/videoN devnode; those that want complex setups could use
multiple /dev/videoN nodes.
+
+/* Gstreamer bug https://bugzilla.gnome.org/show_bug.cgi?id=726521
+ * v4l2src does bad (and actually wrong) things when the vidioc_enum_framesizes
+ * function says type V4L2_FRMSIZE_TYPE_STEPWISE, which we do by default.
+ * It's happier if we just don't say anything at all, when it then
+ * sets up a load of defaults that it thinks might work.
+ * If gst_v4l2src_is_broken is non-zero, then we remove the function from
+ * our function table list (actually switch to an alternate set, but same
+ * result).
+ */
+static int gst_v4l2src_is_broken;
+module_param(gst_v4l2src_is_broken, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(gst_v4l2src_is_broken, "If non-zero, enable workaround for Gstreamer");
Not sure if I liked this hack here. AFAIKT, GStreamer fixed the bug with
V4L2_FRMSIZE_TYPE_STEPWISE already.
I will double check on Monday. The main Raspberry Pi distribution is
based on Debian, so packages can be quite out of date. This bug
certainly affected Wheezy, but I don't know for certain about Jessie.
Sid still hasn't been adopted.
Well, at the RPi distro, the best would be to backport the gst patches
that fixed the bug instead, as it would affect other V4L2 hardware
connected via USB too.
Also be aware that exactly the same issue of not supporting
V4L2_FRMSIZE_TYPE_STEPWISE affects Chromium for WebRTC, and they seem
not to be too bothered about fixing it -
https://bugs.chromium.org/p/chromium/issues/detail?id=249953
Now admittedly it's not the kernel's responsibility to work around
application issues, but if it hobbles a board then that is an issue.
Those lazy maintainers... :-)
+ for (k = 0; k < ARRAY_SIZE(formats); k++) {
+ fmt = &formats[k];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+
+ if (k == ARRAY_SIZE(formats))
+ return NULL;
Again, doesn't the formats depend on the camera sensor module?
Not in this case.
You're at the end of a full ISP processing pipe, and there is the option
for including either JPEG, MJPEG, or H264 encoding on the end. It is
supported to ask the camera component which formats it supports, but
you'll still need a conversion table from those MMAL types to V4L2
enums, and options for adding the encoded formats.
The better would be to split those GPU encoders on a mem2mem driver.
This way, if all the userspace want is the raw images, they can
get it without passing though a GPU pipeline.
The big problem here is that the user doesn't really know what
formats are produced by the camera from those that are post-processed.
On applications that require low latency, that could have a big
impact. For example, if someone is using a RPi on a robot or on
a self-piloted drone, the lowest latency the better.
+ (int)dev->capture.kernel_start_ts.
+ tv_sec,
+ (int)dev->capture.kernel_start_ts.
+ tv_usec,
+ dev->capture.vc_start_timestamp, pts,
+ (int)timestamp.tv_sec,
+ (int)timestamp.tv_usec);
+ buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL +
+ timestamp.tv_usec * 1000ULL;
Not sure if I understood the above logic... Why don't you just do
buf->vb.vb2_buf.timestamp = ktime_get_ns();
What's the processing latency through the ISP and optional
H264/MJPG/JPEG encode to get to this point? Typically you're looking at
30-80ms depending on exposure time and various other factors, which
would be enough to put A/V sync out if not compensated for.
The GPU side is timestamping all buffers with the CSI frame start
interrupt timestamp, but based on the GPU STC. There is a MMAL call to
read the GPU STC which is made at streamon (stored in
dev->capture.vc_start_timestamp), and therefore this is taking a delta
from there to get a more accurate timestamp.
Ah, so this is due to the extra latency introduced by GPU.
(An improvement would be to reread it every N seconds to ensure there
was no drift, but the Linux kernel tick is actually off the same clock,
so it is only clock corrections that would introduce a drift).
As I understand it UVC is doing a similar thing, although it is trying
to compensate for clock drift too.
What happens when daylight saving time changes is applied? Will it
indicate an one hour latency?
Now one could argue that ideally you want the timestamp for the start of
exposure, but there is no event outside of the sensor to trigger that.
You could compute it, but the exposure time control loop is running on
the GPU so the kernel doesn't know the exposure time. It's also a bit of
a funny thing anyway when dealing with rolling shutter sensors and
therefore considering which line you want the start of exposure for.
It seems that you're fixing the bug at the steps used by
v4l_bound_align_image() by rounding up the buffer size. That's wrong!
Just ensure that the width/height will be a valid resolution and
remove this hack.
No, this is working around the fact that very few clients respect
bytesperline (eg QV4L2 and libv4lconvert for many of the formats).
If you find a bug on any clients that we maintain (qv4l2, libv4l,
tvtime, xawtv), please submit us a patch. If this issue was fixed
when you noticed (in 2013, as you're saying below), then we wouldn't
need to concern about it nowadays ;)
The ISP needs to be writing to buffers with the stride being a multiple
of 32, and height a multiple of 16 (and that includes between planes of
YUV420). V4L2 appears not to allow that, therefore there is then a
second operation run in-place on the buffer to remove that padding, but
the buffer needs to be sized sufficiently to handle the padded image first.
I had a conversation with Hans back in 2013 with regard this, and there
wasn't a good solution proposed. It could potentially be specified using
the cropping API, but that pushes the responsibility back onto every
client app to drive things in a very specific manner. If they don't
respect bytesperline they are even less likely to handle cropping.
You could restrict the resolution to being a multiple of 32 on the width
and 16 on the height, but in doing so you're not exposing the full
capabilities.
I'm open to suggestions as to how V4L2 can do this without just beating
up client apps who do the wrong thing.
Multiplanar formats seem not to be an option as the ISP is expecting one
contiguous buffer to be provided to take all the planes, but the
multiplanar stuff supplies multiple independent buffers. Again please
correct me if I'm wrong on that.
Not sure if I fully understand what happens there... Does it add
alignment pads in the middle of the image, or just at the end of
the buffer? If such pads are added in the middle of the image, it
is actually violating the fourcc formats, as they're not meant to
have PADs inside it.
+ /* format dependant port setup */
+ switch (mfmt->mmal_component) {
+ case MMAL_COMPONENT_CAMERA:
+ /* 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 =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+ output[MMAL_CAMERA_PORT_VIDEO];
+ else
+ camera_port = port =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+ output[MMAL_CAMERA_PORT_CAPTURE];
Not sure if I got this... What are you intending to do here?
As noted above, what do you consider a still when dealing with raw RGB
or YUV buffers. This is switching between video and stills quality
processing based on resolution.
That sounds an ugly hack. Unlikely to be accepted upstream.
+static int set_camera_parameters(struct vchiq_mmal_instance *instance,
+ struct vchiq_mmal_component *camera,
+ struct bm2835_mmal_dev *dev)
+{
+ int ret;
+ struct mmal_parameter_camera_config cam_config = {
+ .max_stills_w = dev->max_width,
+ .max_stills_h = dev->max_height,
+ .stills_yuv422 = 1,
+ .one_shot_stills = 1,
+ .max_preview_video_w = (max_video_width > 1920) ?
+ max_video_width : 1920,
+ .max_preview_video_h = (max_video_height > 1088) ?
+ max_video_height : 1088,
Hmm... why do you need to limit the max resolution to 1920x1088? Is it
a limit of the MMAL/firmware?
Memory usage.
Video mode runs as an optimised pipeline so requires multiple frame buffers.
Stills mode typically has to stop the sensor, reprogram for full res
mode, stream for one frame, and then stops the sensor again, therefore
only one stills res buffer is required.
If you've specified video mode to run at more than 1080P, then the GPU
needs to be told up front so that it can allocate the extra memory.
I see. One additional reason why it would be good if the capture
driver could run independently from GPU. That way, only the
encoding codecs would have such restriction.