[libcamera-devel] [PATCH v3 2/3] libcamera: Add V4L2 Device object

Kieran Bingham kieran.bingham at ideasonboard.com
Wed Jan 16 13:07:23 CET 2019


Hi Jacopo,

On 16/01/2019 11:11, Jacopo Mondi wrote:

<snip>
>>
>> The getDriver() and getCard() wraps the casting required again into the
>> class definition so that it doesn't have to be done in arbitrary places
>> in the code.
>>
>> I expect to add next:
>>
>>   V4L2Device::driverName() { return caps_.getDriver(); }
>>   V4L2Device::deviceName() { return caps_.getCard(); }
>> 	// Or ? getDeviceName()?
>>   V4L2Device::busName() { return caps_.getBus(); }
>> 	// (Yes, I'll add this one in to the V4L2Capabiltiy)
>>
>> I anticipate that these strings will be useful to you in the pipeline
>> classes.
>>
>> The UVC pipeline manager should certainly use them.
>>
> 
> One note I missed in both my previous comments: getter methods are named as
> the member field they access, without the "get" prefix.

I can't do that here.
If I name the method the same as the base struct member I get:

../src/libcamera/include/v4l2_device.h: In member function
‘std::__cxx11::string libcamera::V4L2Capability::driver() const’:
../src/libcamera/include/v4l2_device.h:23:58: error: invalid use of
member function ‘std::__cxx11::string
libcamera::V4L2Capability::driver() const’ (did you forget the ‘()’ ?)
  std::string driver() const { return std::string((char *)driver); }


>>> I won't push anymore on this though.
>>
>> I don't mind the push ... I knew this 'wrapping' would be potentially
>> controversial it's partly me trying to experiment with good ways to
>> interact with the Kernel API.
>>
>> At the moment, I must say I really like it though ...
>> 	 <waits for the tumbleweed to pass if I'm the only one>
>>
>> Especially with the ease and cleanliness for exposing the capability
>> strings.
>>
> 
> I'll let other express concerns, if any. Otherwise that's fine with
> me.

Ok thanks,


>>>> +
>>>> +	bool isCapture() const { return capabilities & V4L2_CAP_VIDEO_CAPTURE; }
>>>
>>> You pointed out in your self-review this was meant to be changed,
>>> right?
>>
>> Half-right.
>>
>> Then based on your other comments regarding MPLANE/Single Plane I
>> decided to drop MPLANE support.
>>
>> We don't need it yet, the IPU3 doesn't support MPLANE, the RCAR-VIN
>> doesn't support MPLANE, UVC doesn't support MPLANE ...
>>
> 
> Are you sure?
> 
> - entity 4: ipu3-cio2 0 (1 pad, 1 link)
>             type Node subtype V4L flags 0
>             device node name /dev/video0
> 
> 
> # v4l2-ctl -D -d /dev/video0
> Driver Info (not using libv4l2):
> 	Driver name   : ipu3-cio2
> 	Card type     : Intel IPU3 CIO2
> 	Bus info      : PCI:0000:00:14.3
> 	Driver version: 4.20.0
> 	Capabilities  : 0x84201000
> 		Video Capture Multiplanar       <---------------

Hrm ... my grep foo failed me then ...

OK - so MPLANE /is/ back on the requirements list :)

> 		Streaming
> 		Extended Pix Format
> 		Device Capabilities
> 	Device Caps   : 0x04201000
> 		Video Capture Multiplanar
> 		Streaming
> 		Extended Pix Format
> 
>>
>>>> +	bool hasStreaming() const { return capabilities & V4L2_CAP_STREAMING; }
>>>> +};
>>>> +
>>>> +class V4L2Device
>>>> +{
>>>> +public:
>>>> +	V4L2Device() = delete;
>>>
>>> Should this be private?
>>
>> I wondered that - but I figured - it doesn't matter if it's public or
>> private. It's declaring that it's gone. And I thought it was better to
>> keep the constructors (or lack of) and destructors together.
>>
>> If this is something we want to standardize (keeping deletions in
>> private:) I can move it.
>>
> 
> No big deal, right...

I also realise I should add a deletion for the copy constructor...

<added for next spin>

<snip>

>>>> +/**
>>>> + * \brief Open a V4L2 device and query properties from the device.
>>>> + * \return 0 on success, or a negative error code otherwise
>>>> + */
>>>> +int V4L2Device::open()
>>>> +{
>>>> +	int ret;
>>>> +
>>>> +	if (isOpen()) {
>>>> +		LOG(Error) << "Device already open";
>>>> +		return -EBUSY;
>>>> +	}
>>>> +
>>>> +	ret = ::open(devnode_.c_str(), O_RDWR);
>>>> +	if (ret < 0) {
>>>> +		ret = -errno;

This assignment feels a little redundant.

I agree on only setting the fd_ = ret if success is good - but I'm
feeling like I can save a line (think of the bits) and just return -errno?


>>>> +		LOG(Error) << "Failed to open V4L2 device " << devnode_
>>>> +			   << " : " << strerror(ret);
>>>
>>> strerror(-ret)
>>>
>>> Even if in this case you could have used errno directly. Sorry, my
>>> comment might has mis-lead you
>>
>> Ahh oops - and good spot.
>>
>> But yes - I'd much rather reference the errno directly for strerror().
>>
>>
>>>
>>>> +		return ret;
>>>> +	}
>>>> +	fd_ = ret;
>>>> +
>>>> +	ret = ioctl(fd_, VIDIOC_QUERYCAP, &caps_);
>>>

<snip>

>>>> +/**
>>>> + * \brief Check if device is successfully opened
>>>> + */
>>>> +bool V4L2Device::isOpen() const
>>>> +{
>>>> +	return (fd_ != -1);
>>>
>>> Ah, I see what you've done here (return with no () )
>>>
>>> 	bool isCapture() const { return capabilities & V4L2_CAP_VIDEO_CAPTURE; }
>>
>> Ah I've been caught! (ok well it wasn't intentional hehe)
>>
>> I /almost/ want to add () to the isCapture() but I don't want to
>> increase that line length...
>>
>> /me cries a little and does:
>>
>>    s/(fd_ != -1)/fd != -1/
>>
> 
> As you like the most!

I've removed the brackets to simplify.


> 
> Thanks
>   j

<snip>
-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list